Это не сравнение с 0xc0
, это логическая операция И с 0xc0
.
Битовая маска 0xc0
равна 11 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 и подсчет всех байтов, которые не являются байтами продолжения (т. Е. Он получает длину строки, как объявлено). См. эту ссылку на википедию для более подробной информации и превосходную статью Джоэла Спольски для начинающих.
Кстати, интересно. Вы можете классифицировать байты в потоке UTF-8 следующим образом:
- Если для старшего бита установлено значение
0
, это значение будет одним байтом.
- С двумя старшими битами, установленными на
10
, это байт продолжения.
- В противном случае это первый байт многобайтовой последовательности, а число начальных
1
битов указывает, сколько всего байтов для этой последовательности (110...
означает два байта, 1110...
означает три байта, и т.д.).