UTF-8和Unicode,0xC0和0x80是什么意思?

58

我最近几天一直在阅读有关Unicode和UTF-8的内容,经常会看到类似于这样的按位比较:

int strlen_utf8(char *s) 
{
  int i = 0, j = 0;
  while (s[i]) 
  {
    if ((s[i] & 0xc0) != 0x80) j++;
    i++;
  }
  return j;
}

有人可以澄清一下与0xc0进行AND运算并检查它是否是最高有效位的比较吗?

谢谢!

编辑:应该用“按位与”而不是“比较”,我用错了词 ;)

1个回答

108

这不是与0xc0进行比较,而是进行逻辑AND操作与0xc0

位掩码0xc011 00 00 00,所以AND的作用是仅提取前两个位:

    ab cd ef gh
AND 11 00 00 00
    -- -- -- --
  = ab 00 00 00

这时将它与 0x80 (二进制 10 00 00 00) 进行比较。换句话说,if 语句是检查值的前两位是否不等于 10

"为什么呢?" 您可能会问。好问题!答案是,在 UTF-8 中,所有以比特模式 10 开头的字节都是多字节序列的后续字节:

                    UTF-8
Range              Encoding  Binary value
-----------------  --------  --------------------------
U+000000-U+00007f  0xxxxxxx  0xxxxxxx

U+000080-U+0007ff  110yyyxx  00000yyy xxxxxxxx
                   10xxxxxx

U+000800-U+00ffff  1110yyyy  yyyyyyyy xxxxxxxx
                   10yyyyxx
                   10xxxxxx

U+010000-U+10ffff  11110zzz  000zzzzz yyyyyyyy xxxxxxxx
                   10zzyyyy
                   10yyyyxx
                   10xxxxxx
所以,这段小代码会遍历你的UTF-8字符串中的每个字节,并计算所有不是连续字节的字节数(也就是获取字符串的长度,正如宣传的那样)。查看这个维基百科链接以获取更多详细信息,Joel Spolsky的优秀文章则提供了一个入门指南。
顺便说一下,你可以将UTF-8流中的字节分类如下:
  • 如果高位为0,则它是单字节值。
  • 如果两个高位设置为10,则它是一个连续字节。
  • 否则,它就是一个多字节序列的第一个字节,前导的1位数表示该序列总共有多少个字节(110...表示两个字节,1110...表示三个字节,依此类推)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接