Usando Unicode en el código fuente de C ++

¿Cuál es la encoding estándar del código fuente de C ++? ¿El estándar de C ++ incluso dice algo sobre esto? ¿Puedo escribir fuente C ++ en Unicode?

Por ejemplo, ¿puedo usar caracteres no ASCII como caracteres chinos en los comentarios? Si es así, ¿está permitido Unicode completo o solo un subconjunto de Unicode? (por ejemplo, esa primera página de 16 bits o como se llame).

Además, ¿puedo usar Unicode para cadenas? Por ejemplo:

Wstring str=L"Strange chars: â Țđ ě €€"; 

La encoding en C ++ es bastante complicada. Aquí está mi entendimiento de eso.

Cada implementación debe admitir caracteres del conjunto de caracteres básicos de origen . Estos incluyen caracteres comunes enumerados en §2.2 / 1 (§2.3 / 1 en C ++ 11). Estos personajes deberían encajar en un solo char . Además, las implementaciones tienen que admitir una manera de nombrar otros caracteres usando un modo llamado universal-character-names y se parecen a \uffff o \Uffffffff y se pueden usar para referirse a caracteres Unicode. Un subconjunto de ellos se puede utilizar en identificadores (enumerados en el Anexo E).

Todo esto es agradable, pero la asignación de los caracteres en el archivo a los caracteres de origen (utilizados en tiempo de comstackción) está definida por la implementación. Esto constituye la encoding utilizada. Esto es lo que dice literalmente (versión C ++ 98):

Los caracteres del archivo de origen físico se asignan, de una manera definida por la implementación, al conjunto de caracteres de origen básico (introduciendo caracteres de nueva línea para los indicadores de fin de línea) si es necesario. Las secuencias de Trigraph (2.3) se reemplazan por representaciones internas de un solo carácter correspondientes. Cualquier carácter de archivo de origen que no esté en el juego de caracteres de origen básico (2.2) se reemplaza por el nombre de carácter universal que designa ese carácter. (Una implementación puede usar cualquier encoding interna, siempre que se encuentre un carácter extendido real en el archivo fuente, y se maneje el mismo carácter extendido expresado en el archivo fuente como un nombre de carácter universal (es decir, usando la notación \ uXXXX) equivalentemente.)

Para gcc, puede cambiarlo usando la opción -finput-charset=charset . Además, puede cambiar el carácter de ejecución utilizado para reestablecer valores en tiempo de ejecución. La opción adecuada para esto es -fexec-charset=charset para char (por defecto es utf-8 ) y -fwide-exec-charset=charset (que por defecto es utf-16 o utf-32 dependiendo del tamaño de wchar_t ) .

El estándar de C ++ no dice nada sobre la encoding de archivos de código fuente, hasta donde yo sé.

La encoding habitual es (o solía ser) ASCII de 7 bits: algunos comstackdores (Borland’s, por ejemplo) rechazarían los caracteres ASCII que usaban el bit alto. No hay ninguna razón técnica para que los caracteres Unicode no se puedan usar, si su comstackdor y editor los aceptan, la mayoría de las herramientas modernas basadas en Linux y muchos de los mejores editores basados ​​en Windows manejan la encoding UTF-8 sin problemas, aunque yo No estoy seguro de que el comstackdor de Microsoft lo haga.

EDITAR: parece que los comstackdores de Microsoft aceptarán archivos codificados en Unicode, pero a veces también producirán errores en ASCII de 8 bits:

 warning C4819: The file contains a character that cannot be represented in the current code page (932). Save the file in Unicode format to prevent data loss. 

Además de la publicación de litb, MSVC ++ también admite Unicode. Entiendo que obtiene la encoding Unicode de la lista de materiales. Definitivamente es compatible con código como int (*♫)(); o const std::set ∅; Si está realmente interesado en la obstrucción del código:

 typedef void ‼; // Also known as \u203C class ooɟ { operator ‼() {} }; 

Hay dos problemas en juego aquí. El primero es qué caracteres están permitidos en el código C ++ (y comentarios), como nombres de variables. El segundo es qué caracteres se permiten en cadenas y literales de cadena.

Como se señaló, los comstackdores de C ++ deben admitir un juego de caracteres basado en ASCII muy restringido para los caracteres permitidos en el código y los comentarios. En la práctica, este juego de caracteres no funcionó muy bien con algunos juegos de caracteres europeos (y especialmente con algunos teclados europeos que no tenían algunos caracteres, como corchetes, disponibles), por lo que el concepto de dígrafos y trigrafos era introducido. Muchos comstackdores aceptan más que este conjunto de caracteres en este momento, pero no hay ninguna garantía.

En cuanto a cadenas y literales de cadenas, C ++ tiene el concepto de un carácter ancho y una cadena de caracteres amplia. Sin embargo, la encoding para ese juego de caracteres no está definida. En la práctica, casi siempre es Unicode, pero no creo que haya ninguna garantía aquí. Los literales de cadena de caracteres anchos parecen L “literal de cadena”, y estos se pueden asignar a std :: wstring.


C ++ 11 agregó soporte explícito para cadenas Unicode y literales de cadena, codificados como UTF-8, UTF-16 big endian, UTF-16 little endian, UTF-32 big endian y UTF-32 little endian.

Para codificar en cadenas, creo que debes usar la notación \ u , por ejemplo:

 std::wstring str = L"\u20AC"; // Euro character 

También vale la pena señalar que los caracteres anchos en C ++ no son realmente cadenas Unicode como tales. Son solo cadenas de caracteres más grandes, generalmente 16, pero a veces 32 bits. Esto está definido por la implementación, sin embargo, IIRC puede tener un wchar_t 8 bits wchar_t No tiene garantía real en cuanto a la encoding en ellos, por lo que si está tratando de hacer algo como procesamiento de texto, probablemente querrá un typedef al máximo tipo de entero adecuado para su entidad Unicode.

C ++ 1x tiene soporte Unicode adicional en forma de literales de cadena de encoding UTF-8 ( u8"text" ), y tipos de datos UTF-16 y UTF-32 ( char16_t y char32_t IIRC) así como las constantes de cadena correspondientes ( u"text" y U"text" ). Sin embargo, la encoding en caracteres especificados sin \uxxxx o \Uxxxxxxxx todavía está definida por la implementación (y no hay soporte de encoding para tipos de cadenas complejas fuera de los literales)

En este contexto, si obtiene la advertencia C4819 de MSVC ++, simplemente cambie la encoding del archivo de origen a “UTF-8 con Bom”.

GCC 4.1 no es compatible con esto, pero GCC 4.4 lo hace, y la última versión de Qt usa GCC 4.4, por lo tanto, utilice “UTF-8 con Bom” como código de fuente de encoding.

AFAIK No está estandarizado ya que puedes poner cualquier tipo de caracteres en cuerdas anchas. Solo tiene que comprobar que su comstackdor está configurado en código fuente Unicode para que funcione correctamente.