tabla sirve que para codificacion caracteres c++ language-lawyer sizeof utf-16

c++ - codificacion - utf-8 html para que sirve



Confundir sizeof(char) por ISO/IEC en codificación de conjunto de caracteres diferente como UTF-16 (5)

Suponiendo que un programa se está ejecutando en un sistema con un conjunto de caracteres de codificación UTF-16. De acuerdo con el lenguaje de programación C ++ - 4to , página 150:

Un char puede contener un caracter del juego de caracteres de la máquina.

→ Creo que una variable char tendrá el tamaño de 2 bytes.

Pero según ISO / IEC 14882: 2014 :

sizeof(char) , sizeof(signed char) y sizeof(unsigned char) son 1 ".

o El lenguaje de programación C ++ - 4to , página 149:

"[...], entonces, por definición, el tamaño de un char es 1"

→ Se fija con el tamaño es 1.

Pregunta: ¿Existe un conflicto entre estas declaraciones anteriores o si el sizeof(char) = 1 solo es un valor predeterminado (definición) y se definirá según la implementación depende de cada sistema?


El estándar de C ++ (y C, para el caso) define efectivamente byte como el tamaño de un tipo de caracteres, no como una cantidad de ocho bits 1 . Según C++11 1.7/1 (mi negrita):

La unidad de almacenamiento fundamental en el modelo de memoria C ++ es el byte. Un byte es al menos lo suficientemente grande como para contener cualquier miembro del conjunto de caracteres de ejecución básico y las unidades de código de ocho bits de la forma de codificación Unicode UTF-8 y está compuesto por una secuencia contigua de bits, cuyo número está definido por la implementación.

Por lo tanto, la expresión sizeof(char) siempre es 1, sin importar qué.

Si desea ver si su variable de línea de base (probablemente la variante unsigned sería la mejor) puede contener un valor de 16 bits, el elemento que desea ver es CHAR_BIT de <climits> . Esto contiene la cantidad de bits en una variable char .

1 Muchos estándares, especialmente los relacionados con protocolos de comunicaciones, usan el término octet más exacto para un valor de ocho bits.


No, no hay conflicto Estas dos declaraciones se refieren a diferentes definiciones de byte .

UTF-16 implica que byte es lo mismo que octeto : un grupo de 8 bits.

En C ++, el byte del lenguaje es lo mismo que char . No hay ninguna limitación sobre cuántos bits puede contener un byte C ++. El número de bits en C ++ - byte se define mediante la constante de macro CHAR_BIT .

Si su implementación C ++ decide usar 16 bits para representar cada carácter, entonces CHAR_BIT será 16 y cada C ++ - byte ocupará dos UTF-16-bytes. sizeof(char) seguirá siendo 1 y los tamaños de todos los objetos se medirán en términos de bytes de 16 bits.


Sí, hay una serie de conflictos y problemas serios con la combinación C ++ de roles para char , pero también la pregunta combina algunas cosas. Entonces, una respuesta directa simple sería como responder "sí", "no" o "no sé" a la pregunta "¿has dejado de golpear a tu esposa?". La única respuesta directa es la "mu" budista , sin formular la pregunta.

Así que comencemos con una mirada a los hechos.

Datos sobre el tipo de caracteres.

La cantidad de bits por char viene dada por la implementación definida CHAR_BIT del encabezado <limits.h> . Este número está garantizado para ser 8 o más grande. Con C ++ 03 y anteriores, esa garantía provino de la especificación de ese símbolo en el estándar C89, que el estándar C ++ notó (en una sección no normativa, pero aún) como "incorporado". Con C ++ 11 y más tarde, el estándar C ++ explícitamente, por sí mismo, otorga la garantía ≥8. En la mayoría de las plataformas CHAR_BIT es 8, pero en algunos procesadores de señales digitales de Texas Instruments probablemente todavía sean 16, y se han utilizado otros valores.

Independientemente del valor de CHAR_BIT el CHAR_BIT sizeof(char) es por definición 1, es decir, no está definido por la implementación:

C ++ 11 §5.3.3 / 1 (en [expr.sizeof]):

" sizeof(char) , sizeof(signed char) y sizeof(unsigned char) son 1.

Es decir, char y sus variantes es la unidad fundamental de direccionamiento de la memoria, que es el significado principal de byte , tanto en el habla común como formalmente en C ++:

C ++ 11 §1.7 / 1 (en [intro.memory]):

" La unidad de almacenamiento fundamental en el modelo de memoria C ++ es el byte .

Esto significa que en los DSP de TI antes mencionados, no hay forma C ++ de obtener punteros a octetos individuales (partes de 8 bits). Y eso a su vez significa que el código que necesita tratar con endianness, o de otra manera necesita tratar los valores de char como secuencias de octetos, en particular para comunicaciones de red, necesita hacer cosas con valores de char que no son significativos en un sistema donde CHAR_BIT es 8. También significa que los literales de cadena estrecha comunes de C ++, si se adhieren al estándar, y si el software estándar de la plataforma usa una codificación de caracteres de 8 bits, desperdiciará la memoria.

El aspecto de desecho fue (o es) abordado directamente en el lenguaje Pascal, que diferencia entre cadenas empaquetadas (múltiples octetos por byte) y cadenas desempaquetadas (un octeto por byte), donde el primero se usa para almacenamiento de texto pasivo, y el segundo es utilizado para un procesamiento eficiente.

Esto ilustra la combinación básica de tres aspectos en el único char tipo C ++:

  • unidad de direccionamiento de memoria, también conocido como byte,

  • el tipo básico más pequeño (sería bueno con un tipo de octet ), y

  • unidad de valor de codificación de caracteres.

Y sí, esto es un conflicto.

Datos sobre la codificación UTF-16.

Unicode es un gran conjunto de puntos de código de 21 bits, la mayoría de los cuales constituyen caracteres en sí mismos, pero algunos de los cuales se combinan con otros para formar caracteres. Por ejemplo, un personaje con acento como "é" puede formarse combinando puntos de código para "e" y "''" -ascentual. Y como se trata de un mecanismo general, significa que un carácter Unicode puede ser una cantidad arbitraria de puntos de código, aunque generalmente solo es 1.

La codificación UTF-16 era originalmente un esquema de compatibilidad para código basado en los 16 bits originales de Unicode por punto de código, cuando Unicode se extendía a 21 bits por punto de código. El esquema básico es que los puntos de código en los rangos definidos de Unicode original se representan como ellos mismos, mientras que cada nuevo punto de código Unicode se representa como un par sustituto de valores de 16 bits. Se utiliza una pequeña gama de Unicode original para los valores de par sustituto.

En ese momento, los ejemplos de software basados ​​en 16 bits por punto de código incluían Windows de 32 bits y el lenguaje Java .

En un sistema con byte de 8 bits, UTF-16 es un ejemplo de codificación de texto amplia , es decir, con una unidad de codificación más ancha que la unidad direccionable básica. Las codificaciones de texto orientadas a bytes se conocen entonces como texto estrecho . En un sistema de este tipo, C ++ char encaja en este último, pero no en el primero.

En C ++ 03, el único tipo integrado adecuado para la unidad de codificación de texto amplio era wchar_t .

Sin embargo, el estándar C ++ requiere efectivamente que wchar_t sea ​​adecuado para un punto de código , que para el moderno Unicode de 21 bits por punto significa que necesita ser de 32 bits. Por lo tanto, no hay ningún tipo dedicado C ++ 03 que se ajuste a los requisitos de los valores de codificación UTF-16, 16 bits por valor. Debido a razones históricas, el sistema más prevalente basado en UTF-16 como codificación de texto amplia, concretamente Microsoft Windows, define wchar_t como 16 bits, lo que después de la extensión de Unicode ha estado en flagrante contradicción con el estándar, pero entonces, el estándar no es práctico En relación con este problema. Algunas plataformas definen wchar_t como 32 bits.

C ++ 11 introdujo nuevos tipos char16_t y char32_t , donde el primero es (diseñado para ser) adecuado para valores de codificación UTF-16.

Sobre la pregunta.

Con respecto a la suposición declarada de la pregunta

"Un sistema con conjunto de caracteres de codificación UTF-16"

esto puede significar una de dos cosas:

  • un sistema con UTF-16 como la codificación estrecha estándar, o
  • un sistema con UTF-16 como la codificación ancha estándar.

Con UTF-16 como la codificación estándar estrecha CHAR_BIT ≥ 16, y (por definición) sizeof(char) = 1. No conozco ningún sistema, es decir, parece ser hipotético. Sin embargo, parece ser el significado asumido tácitamente en otras respuestas actuales.

Con UTF-16 como codificación ancha estándar, como en Windows, la situación es más compleja, porque el estándar de C ++ no está a la altura de la tarea. Pero, para usar Windows como un ejemplo, una posibilidad práctica es que sizeof(wchar_t) = 2. Y uno debe notar que el estándar está en conflicto con la práctica existente y las consideraciones prácticas para este problema, cuando lo ideal es que los estándares estandaricen el práctica existente, donde existe tal.

Ahora finalmente estamos en condiciones de lidiar con la pregunta,

" ¿Existe un conflicto entre estas declaraciones anteriores o si el sizeof(char) = 1 solo es un valor predeterminado (definición) y se definirá según la implementación depende de cada sistema?

Esta es una dicotomía falsa. Las dos posibilidades no son opuestas. Tenemos

  • De hecho, hay un conflicto entre char como unidad de codificación de caracteres y como unidad de direccionamiento de memoria (byte). Como se señaló, el lenguaje Pascal tiene la palabra clave packed para tratar con un aspecto de ese conflicto, a saber, el almacenamiento frente a los requisitos de procesamiento. Y hay otro conflicto entre los requisitos formales de wchar_t y su uso para la codificación UTF-16 en el sistema más utilizado que emplea la codificación UTF-16, a saber, Windows.

  • sizeof(char) = 1 por definición: no depende del sistema.

  • CHAR_BIT es la implementación definida, y está garantizado ≥ 8.


Sin citar un estándar, es fácil dar simplemente una respuesta porque:

La definición de byte no es de 8 bits . Byte es cualquier tamaño pero la unidad de memoria direccionable más pequeña. Más comúnmente es de 8 bits, pero no hay razón para no tener 16 bits de bytes.

El estándar C ++ ofrece más restricciones porque debe ser de al menos 8 bits.

Entonces, no hay problema con que sizeof (char) sea siempre 1, sin importar qué. A veces se colocará en 8 bits, a veces 16 bits y así sucesivamente.


Una char se define como 1 byte. Un byte es la unidad direccionable más pequeña. Esto es de 8 bits en sistemas comunes, pero en algunos sistemas es de 16 bits, o 32 bits, o cualquier otra cosa (pero debe ser de al menos 8 para C ++).

Es algo confuso porque en la jerga popular se usa byte para lo que técnicamente se conoce como octeto (8 bits).

Entonces, sus citas segunda y tercera son correctas. La primera cita es, estrictamente hablando, incorrecta.

Según lo definido por [intro.memory] / 1 en el Estándar C ++, char solo necesita poder contener el conjunto de caracteres de ejecución básica que tiene aproximadamente 100 caracteres (todos los cuales aparecen en el rango 0 - 127 de ASCII), y el octetos que componen la codificación UTF-8. Tal vez eso es lo que el autor quiso decir con el conjunto de caracteres de la máquina .

En un sistema donde el hardware es octeto direccionable pero el conjunto de caracteres es Unicode, es probable que el char permanezca en 8 bits. Sin embargo, hay tipos char16_t y char32_t (agregados en C ++ 11) que están diseñados para ser usados ​​en su código en lugar de char para sistemas que tienen conjuntos de caracteres de 16 o 32 bits.

Entonces, si el sistema va con char16_t entonces usaría std::basic_string<char16_t> lugar de std::string , y así sucesivamente.

Exactamente cómo se debe manejar UTF-16 dependerá de los detalles de la implementación elegida por el sistema. Unicode es un conjunto de caracteres de 21 bits y UTF-16 es una codificación multibyte de él; por lo que el sistema podría seguir la ruta de Windows y usar std::basic_string<char16_t> con codificación UTF-16 para cadenas; o podría ir por std::basic_string<char32_t> con puntos de código Unicode sin std::basic_string<char32_t> como los caracteres.

La publicación de Alf entra en más detalles sobre algunos de los problemas que pueden surgir.