C99 o anterior
El estándar C (C99) proporciona caracteres anchos y caracteres multibyte, pero como no hay garantía sobre lo que pueden contener esos caracteres anchos, su valor es algo limitado. Para una implementación dada, brindan soporte útil, pero si su código debe poder moverse entre implementaciones, no hay garantía suficiente de que serán útiles.
En consecuencia, el enfoque sugerido por Hans van Eck (que consiste en escribir un resumen de la biblioteca ICU - Componentes internacionales para Unicode -) es sólido, en mi opinión.
La codificación UTF-8 tiene muchos méritos, uno de los cuales es que si no se mete con los datos (truncándolos, por ejemplo), puede ser copiado por funciones que no son plenamente conscientes de las complejidades de UTF-8 codificación. Este no es categóricamente el caso de wchar_t
.
Unicode en su totalidad es un formato de 21 bits. Es decir, Unicode reserva puntos de código de U + 0000 a U + 10FFFF.
Una de las cosas útiles de los formatos UTF-8, UTF-16 y UTF-32 (donde UTF significa Formato de transformación Unicode; consulte Unicode ) es que puede convertir entre las tres representaciones sin pérdida de información. Cada uno puede representar cualquier cosa que los demás puedan representar. Tanto UTF-8 como UTF-16 son formatos de varios bytes.
UTF-8 es bien conocido por ser un formato multibyte, con una estructura cuidadosa que hace posible encontrar el inicio de los caracteres en una cadena de manera confiable, comenzando en cualquier punto de la cadena. Los caracteres de un solo byte tienen el bit alto establecido en cero. Los caracteres de varios bytes tienen el primer carácter que comienza con uno de los patrones de bits 110, 1110 o 11110 (para caracteres de 2 bytes, 3 bytes o 4 bytes), y los bytes siguientes siempre comienzan con 10. Los caracteres de continuación siempre están en el rango 0x80 .. 0xBF. Existen reglas que establecen que los caracteres UTF-8 deben representarse en el formato mínimo posible. Una consecuencia de estas reglas es que los bytes 0xC0 y 0xC1 (también 0xF5..0xFF) no pueden aparecer en datos UTF-8 válidos.
U+0000 .. U+007F 1 byte 0xxx xxxx
U+0080 .. U+07FF 2 bytes 110x xxxx 10xx xxxx
U+0800 .. U+FFFF 3 bytes 1110 xxxx 10xx xxxx 10xx xxxx
U+10000 .. U+10FFFF 4 bytes 1111 0xxx 10xx xxxx 10xx xxxx 10xx xxxx
Originalmente, se esperaba que Unicode fuera un conjunto de códigos de 16 bits y que todo encajara en un espacio de código de 16 bits. Desafortunadamente, el mundo real es más complejo y tuvo que expandirse a la codificación actual de 21 bits.
Por tanto, UTF-16 es un conjunto de códigos de una sola unidad (palabra de 16 bits) para el 'Plano multilingüe básico', es decir, los caracteres con puntos de código Unicode U + 0000 .. U + FFFF, pero utiliza dos unidades (32 bits) para caracteres fuera de este rango. Por lo tanto, el código que funciona con la codificación UTF-16 debe poder manejar codificaciones de ancho variable, al igual que UTF-8. Los códigos para los caracteres de doble unidad se denominan sustitutos.
Los sustitutos son puntos de código de dos rangos especiales de valores Unicode, reservados para su uso como valores iniciales y finales de unidades de código emparejadas en UTF-16. Los sustitutos principales, también llamados altos, son de U + D800 a U + DBFF, y los sustitutos finales o bajos son de U + DC00 a U + DFFF. Se les llama sustitutos, ya que no representan personajes directamente, sino solo como pareja.
UTF-32, por supuesto, puede codificar cualquier punto de código Unicode en una sola unidad de almacenamiento. Es eficiente para la computación pero no para el almacenamiento.
Puede encontrar mucha más información en los sitios web de ICU y Unicode.
C11 y <uchar.h>
El estándar C11 cambió las reglas, pero no todas las implementaciones se han puesto al día con los cambios incluso ahora (mediados de 2017). El estándar C11 resume los cambios para el soporte Unicode como:
- Caracteres y cadenas Unicode (
<uchar.h>
) (originalmente especificado en ISO / IEC TR 19769: 2004)
Lo que sigue es un resumen mínimo de la funcionalidad. La especificación incluye:
6.4.3 Nombres de caracteres universales
Sintaxis
nombre-carácter-universal:
\u
hex-quad
\U
hex-quad hex-quad
hex-quad:
dígito-hexadecimal dígito-hexadecimal dígito-hexadecimal dígito-hexadecimal
7.28 utilidades Unicode <uchar.h>
El encabezado <uchar.h>
declara tipos y funciones para manipular caracteres Unicode.
Los tipos declarados son mbstate_t
(descritos en 7.29.1) y size_t
(descritos en 7.19);
char16_t
que es un tipo entero sin signo utilizado para caracteres de 16 bits y es del mismo tipo que uint_least16_t
(descrito en 7.20.1.2); y
char32_t
que es un tipo entero sin signo utilizado para caracteres de 32 bits y es del mismo tipo que uint_least32_t
(también descrito en 7.20.1.2).
(Traduciendo las referencias cruzadas: <stddef.h>
define size_t
,
<wchar.h>
define mbstate_t
y <stdint.h>
define uint_least16_t
y uint_least32_t
). El <uchar.h>
encabezado también define un conjunto mínimo de funciones de conversión (reiniciables):
mbrtoc16()
c16rtomb()
mbrtoc32()
c32rtomb()
Existen reglas sobre qué caracteres Unicode se pueden usar en identificadores usando notaciones \unnnn
o \U00nnnnnn
. Es posible que deba activar activamente el soporte para dichos caracteres en identificadores. Por ejemplo, GCC requiere -fextended-identifiers
permitir estos en identificadores.
Tenga en cuenta que macOS Sierra (10.12.5), por nombrar solo una plataforma, no es compatible <uchar.h>
.