自:
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个字节的多字节)0xFFFFFF
?答案 0 :(得分:7)
strchr()
似乎只适用于您的多字节字符。
内存中的实际字符串是
... c,o,n,t,a,i,n,s,' ',0xC3,0xA9,' ',w ...
当您致电strchr()
时,您实际上只搜索0xA9
,这是低8位。这就是为什么pos[-1]
具有多字节字符的第一个字节的原因:它在搜索过程中被忽略了。
您的系统上已对char
进行了签名,这就是为什么您的字符在打印出来时会进行符号扩展(0xFFFFFF
)。
至于警告,似乎编译器试图告诉你,你正在做一些奇怪的事情,你就是这样。不要忽视它。
答案 1 :(得分:4)
这就是问题所在。它似乎工作。首先,如果你在其中放入多字节字符,它完全取决于编译器在字符串中放置的内容,如果它确实根本编译它。显然你很幸运(对于幸运的一些恰当的解释),因为它已经填充了你的字符串
.... c3, a9, ' ', 'w', etc
并且您正在寻找c3a9
,因为它可以很容易地找到它。 strchr的手册页说:
strchr()函数返回指向字符串s中第一次出现的c(转换为char)的指针
所以你将c3a9传递给它,它被转换为值{a9'的char
。它找到a9
字符,然后返回指向它的指针。
ffffff
前缀是因为您输出的是有符号字符作为32位十六进制数字,因此它会为您扩展它。这是预期的。
问题在于“未定义的行为”就是这样。它几乎可以正常工作。它可能不会,视情况而定。
而且差不多了。你没有获得指向多字节字符的指针,你得到一个指向它中间的指针,(我很惊讶你把它解释为工作)。如果多字节字符已经评估为0xff20,那么你会被指向字符串中较早的某个位置。