2010-10-12 20 views
36

He estado leyendo acerca de Unicode y UTF-8 en el último par de días y me vienen a menudo a través de una comparación bit a bit similar a esto:UTF-8 y Unicode, ¿qué pasa con 0xC0 y 0x80?

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

Puede alguien aclarar la comparación con 0xc0 y comprobar si es la parte más significante ?

¡Gracias!

EDIT: AND, no comparación, utiliza la palabra equivocada;)

Respuesta

71

No es una comparación con 0xc0, es una operación lógica AND con 0xc0.

la máscara de bits 0xc0 es 11 00 00 00 así que lo que la Y está haciendo es extraer solamente los dos bits superiores:

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

Esto se compara entonces con 0x80 (binario 10 00 00 00). En otras palabras, la instrucción if comprueba si los dos bits superiores del valor no son iguales a 10.

"¿Por qué?", ​​Oí que preguntas. Bueno, esa es una buena pregunta. La respuesta es que, en UTF-8, todos los bytes que comienzan con el patrón de bits 10 son bytes posteriores de una secuencia multi-byte:

    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 

Por lo tanto, lo que este pequeño fragmento está haciendo está pasando por cada byte de su cadena UTF-8 y contando todos los bytes que no son bytes de continuación (es decir, está obteniendo la longitud de la cadena, como se anuncia). Vea this wikipedia link para más detalles y Joel Spolsky's excellent article para una imprimación.


Un lado interesante por cierto. Se puede clasificar en un flujo de bytes UTF-8 de la siguiente manera:

  • Con el bit alto establecido para 0, es un único valor de byte.
  • Con los dos bits altos configurados en 10, es un byte de continuación.
  • De lo contrario, es el primer byte de una secuencia de varios bytes y el número de bits 1 indica cuántos bytes hay en total para esta secuencia (110... significa dos bytes, 1110... significa tres bytes, etc.).
+1

awesome explanation. ayudó mucho Gracias. –