UTF-8&;Unicode,什么';带0xC0和0x80的s?

UTF-8&;Unicode,什么';带0xC0和0x80的s?,unicode,utf-8,Unicode,Utf 8,在过去的几天里,我一直在阅读有关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的比较并检查它是否是最高有效位吗 谢谢大家! 编辑:ANDed,不是比较,使用了错误的单词;) 它不是与0xc0的

在过去的几天里,我一直在阅读有关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的比较并检查它是否是最高有效位吗

谢谢大家!


编辑:ANDed,不是比较,使用了错误的单词;)

它不是与
0xc0
的比较,而是与
0xc0
的逻辑AND运算

位掩码
0xc0
11 00 00
,因此AND所做的是仅提取前两位:

    ab cd ef gh
AND 11 00 00 00
    -- -- -- --
  = ab 00 00 00
然后将其与
0x80
(二进制
10 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字符串的每个字节,并计算所有不是延续字节的字节(即,它得到了字符串的长度,如广告所示)。有关更多详细信息和底漆,请参阅


顺便提一下,这是一个有趣的旁白。您可以按如下方式对UTF-8流中的字节进行分类:

  • 高位设置为
    0
    ,则为单字节值
  • 当两个高位设置为
    10
    时,它是一个连续字节
  • 否则,它是多字节序列的第一个字节,前导
    1
    位的数量表示该序列总共有多少字节(
    110…
    表示两个字节,
    1110…
    表示三个字节,以此类推)