strcmp 和 strstr 测试二进制等价性吗?
Do strcmp and strstr test binary equivalence?
https://docs.microsoft.com/en-us/windows/win32/intl/security-considerations--international-features
这个网页让我感到奇怪。
显然,一些 windows api 可能认为两个字符串相等,但实际上它们是不同的字节序列。
我想知道 C 标准库在这方面的表现如何。
换句话说,strcmp(a,b)==0
是否意味着strlen(a)==strlen(b)&&memcmp(a,b,strlen(a))==0
?
以及其他字符串函数,包括宽字符版本?
编辑:
例如,CompareStringW
等于 L"\x00C5" 和 L"\x212B"
printf("%d\n",CompareStringW(LOCALE_INVARIANT,0,L"\x00C5",-1,L"\x212B",-1)==CSTR_EQUAL);
输出 1
我想问的是 C 库函数是否永远不会像这样
- 使用不同编码的两个字符串可以相同,即使它们的字节表示不同。
- 标准库
strcmp
确实比较普通的“字符”字符串,在这种情况下 strcmp(a,b)==0 implies strlen(a)==strlen(b)&&memcmp(a,b,strlen(a))==0
- 像
wcscmp
这样的函数要求两个字符串以相同的方式编码,因此它们的字节表示形式应该相同。
常规字符串函数运行 byte-by-byte。 specification 表示:
The sign of a nonzero value returned by the comparison functions memcmp
, strcmp
, and strncmp
is determined by the sign of the difference between the values of the first pair of characters (both interpreted as unsigned char
) that differ in the objects being compared.
strcmp()
和 memcmp()
做同样的比较。唯一的区别是 strcmp()
使用字符串中的空终止符作为限制,memcmp()
为此使用一个参数,而 strncmp()
使用一个限制参数并使用先到者。
宽字符串函数 specification 说:
Unless explicitly stated otherwise, the functions described in this subclause order two wide characters the same way as two integers of the underlying integer type designated by wchar_t
.
wcscmp()
没有另外说明,所以它也是在数字上比较宽字符,而不是通过将它们的编码转换为一些常见的字符表示。 wcscmp()
之于 wmemcmp()
如同 strcmp()
之于 memcmp()
.
另一方面,wcscoll()
比较根据当前语言环境的 LC_COLLATE
类别解释的字符串。所以这可能不等同于 memcmp()
.
对于其他功能,您应该查看文档以查看它们是否引用了语言环境。
Apparently some windows api may consider two strings equal when they are actually different byte sequences.
根据上下文以及您从何处获取这些字符串,这实际上是语义上正确的行为。
有多种方法可以编码 某些字符。例如,德语 'ä'
。在 Unicode 中,这可能是 U+00E4 LATIN SMALL LETTER A WITH DAERHESIS,或者它可能是 U+0308 COMBINING DIAERESIS 和 U+0061 LATIN SMALL LETTER A 的序列。您可能需要一个比较函数来实际比较它们是否相等。或者你可以让它们 not 比较相等,但有一个独立的函数将一种表示转换为另一种表示(“规范化”)。
您可能需要一个比较函数,将 '6'
(六)与 '๖'
(也是六,仅在泰语中)进行比较。 (“规范化”)
字节字符串函数(strcmp()
等)无法做到这些。他们只处理字节序列,并不知道我上面写的任何东西。
至于宽字符串函数(wcscmp()
等),嗯......它们也不是,真的。
in other words, does strcmp(a,b)==0 imply strlen(a)==strlen(b)&&memcmp(a,b,strlen(a))==0? and what about other string functions, including wide character versions?
两者都将测试二进制等价性,因为 C 标准库中没有规范化或规范化字符串的机制。[1]
如果你是实际处理处理字符串(而不是仅仅传递它们,C字节字符串和宽字符串足够了),你应该使用 ICU library,事实上的 标准来处理 C/C++ Unicode。这看起来令人生畏,但实际上需要正确处理所有这些事情。
基本上,任何承诺做同样事情的 C/C++ API 要么 使用 ICU 库本身,要么很可能不做它在宣传什么。
[1]:实际上,strcoll()
/ strxfrm()
和 wcscoll()
/ wcsxfrm()
实际上提供了足够的摆动空间来挤入适当的 Unicode 机制进行整理,但我不知道有哪个实现会真正费心这样做。
https://docs.microsoft.com/en-us/windows/win32/intl/security-considerations--international-features
这个网页让我感到奇怪。 显然,一些 windows api 可能认为两个字符串相等,但实际上它们是不同的字节序列。 我想知道 C 标准库在这方面的表现如何。
换句话说,strcmp(a,b)==0
是否意味着strlen(a)==strlen(b)&&memcmp(a,b,strlen(a))==0
?
以及其他字符串函数,包括宽字符版本?
编辑:
例如,CompareStringW
等于 L"\x00C5" 和 L"\x212B"
printf("%d\n",CompareStringW(LOCALE_INVARIANT,0,L"\x00C5",-1,L"\x212B",-1)==CSTR_EQUAL);
输出 1
我想问的是 C 库函数是否永远不会像这样
- 使用不同编码的两个字符串可以相同,即使它们的字节表示不同。
- 标准库
strcmp
确实比较普通的“字符”字符串,在这种情况下strcmp(a,b)==0 implies strlen(a)==strlen(b)&&memcmp(a,b,strlen(a))==0
- 像
wcscmp
这样的函数要求两个字符串以相同的方式编码,因此它们的字节表示形式应该相同。
常规字符串函数运行 byte-by-byte。 specification 表示:
The sign of a nonzero value returned by the comparison functions
memcmp
,strcmp
, andstrncmp
is determined by the sign of the difference between the values of the first pair of characters (both interpreted asunsigned char
) that differ in the objects being compared.
strcmp()
和 memcmp()
做同样的比较。唯一的区别是 strcmp()
使用字符串中的空终止符作为限制,memcmp()
为此使用一个参数,而 strncmp()
使用一个限制参数并使用先到者。
宽字符串函数 specification 说:
Unless explicitly stated otherwise, the functions described in this subclause order two wide characters the same way as two integers of the underlying integer type designated by
wchar_t
.
wcscmp()
没有另外说明,所以它也是在数字上比较宽字符,而不是通过将它们的编码转换为一些常见的字符表示。 wcscmp()
之于 wmemcmp()
如同 strcmp()
之于 memcmp()
.
另一方面,wcscoll()
比较根据当前语言环境的 LC_COLLATE
类别解释的字符串。所以这可能不等同于 memcmp()
.
对于其他功能,您应该查看文档以查看它们是否引用了语言环境。
Apparently some windows api may consider two strings equal when they are actually different byte sequences.
根据上下文以及您从何处获取这些字符串,这实际上是语义上正确的行为。
有多种方法可以编码 某些字符。例如,德语 'ä'
。在 Unicode 中,这可能是 U+00E4 LATIN SMALL LETTER A WITH DAERHESIS,或者它可能是 U+0308 COMBINING DIAERESIS 和 U+0061 LATIN SMALL LETTER A 的序列。您可能需要一个比较函数来实际比较它们是否相等。或者你可以让它们 not 比较相等,但有一个独立的函数将一种表示转换为另一种表示(“规范化”)。
您可能需要一个比较函数,将 '6'
(六)与 '๖'
(也是六,仅在泰语中)进行比较。 (“规范化”)
字节字符串函数(strcmp()
等)无法做到这些。他们只处理字节序列,并不知道我上面写的任何东西。
至于宽字符串函数(wcscmp()
等),嗯......它们也不是,真的。
in other words, does strcmp(a,b)==0 imply strlen(a)==strlen(b)&&memcmp(a,b,strlen(a))==0? and what about other string functions, including wide character versions?
两者都将测试二进制等价性,因为 C 标准库中没有规范化或规范化字符串的机制。[1]
如果你是实际处理处理字符串(而不是仅仅传递它们,C字节字符串和宽字符串足够了),你应该使用 ICU library,事实上的 标准来处理 C/C++ Unicode。这看起来令人生畏,但实际上需要正确处理所有这些事情。
基本上,任何承诺做同样事情的 C/C++ API 要么 使用 ICU 库本身,要么很可能不做它在宣传什么。
[1]:实际上,strcoll()
/ strxfrm()
和 wcscoll()
/ wcsxfrm()
实际上提供了足够的摆动空间来挤入适当的 Unicode 机制进行整理,但我不知道有哪个实现会真正费心这样做。