为什么`strchr`似乎与多字节字符一起工作,尽管手册免责声明?
从:
man strchr
char * strchr(const char * s,int c);
strchr()函数返回指向字符串s中第一次出现的字符c的指针。
这里“字符”表示“字节”; 这些函数不适用于宽字符或多字节字符。
不过,如果我尝试搜索像é
(UTF-8中的0xC3A9
)这样的多字节字符:
const char str[] = "This string contains é which is a multi-byte character"; char * pos = strchr(str, (int)'é'); printf("%s\n", pos); printf("0x%X 0x%X\n", pos[-1], pos[0]);
我得到以下输出:
这是一个多字节字符
0xFFFFFFC3 0xFFFFFFA9
尽管有警告:
警告:多字符字符常量[-Wmultichar]
所以这是我的问题:
- 什么意味着
strchr
不适用于多字节字符? (它似乎工作,只要int
类型足够大,包含你的多字节,最多4个字节) - 如何摆脱警告,即如何安全地恢复多字节值并将其存储在int中?
- 为什么前缀为
0xFFFFFF
?
strchr()
似乎只适用于您的多字节字符。
内存中的实际字符串是
… c,o,n,t,a,i,n,s,”,0xC3,0xA9,”,w …
当你调用strchr()
,你实际上只搜索0xA9
,它是低8位。 这就是pos[-1]
具有多字节字符的第一个字节的原因:它在搜索过程中被忽略了。
在您的系统上签名一个char
,这就是为什么你打印出来时你的字符符号扩展( 0xFFFFFF
)。
至于警告,似乎编译器试图告诉你,你正在做一些奇怪的事情,你就是这样。 不要忽视它。
那就是问题所在。 它似乎工作。 首先,如果你在其中放入多字节字符,它完全取决于编译器在字符串中放置的内容,如果它确实根本编译它。 显然你很幸运(对于幸运的一些恰当的解释),因为它已经填满了你的字符串
.... c3, a9, ' ', 'w', etc
并且你正在寻找c3a9
,因为它可以很容易地找到它。 strchr的手册页说:
strchr()函数返回指向字符串s中第一次出现的c(转换为char)的指针
所以你将c3a9传递给它,它被转换为值为’a9’的char
。 它找到了a9
字符,并返回指向它的指针。
ffffff
前缀是因为您输出的是带符号的字符作为32位hex数字,因此它会为您扩展它。 这是预期的。
问题是“未定义的行为”就是这样。 它几乎可以正常工作。 它可能不会,视情况而定。
它几乎是。 你没有得到一个指向多字节字符的指针,你得到一个指向它中间的指针,(我很惊讶你把它解释为工作)。 如果多字节字符已经评估为0xff20,那么您将被指向字符串中较早的某个位置。