2010-12-08 42 views
7

De C++ 2003 2,13conflictos: definición de cadena wchar_t en C++ estándar y la implementación de Windows?

Una amplia cadena literal tiene tipo “matriz de n const wchar_t” y tiene una duración de almacenamiento estático, donde n es el tamaño de la cadena como se define a continuación

El tamaño de un literal de cadena ancha es el número total de secuencias de escape, nombres de caracteres universales y otros caracteres, más uno para la terminación L '\ 0'.

De C++ 0x 2.14.5

Una amplia cadena literal tiene el tipo “matriz de n const wchar_t”, donde n es el tamaño de la cadena como se define a continuación

El el tamaño de un char32_t o literal de cadena ancha es el número total de secuencias de escape, nombres de caracteres universales y otros caracteres, más uno para la terminación U '\ 0' o L '\ 0'.

El tamaño de un literal de cadena char16_t es el número total de secuencias de escape, nombres de caracteres universales y otros caracteres, más uno para cada carácter que requiere un par sustituto, más uno para la terminación u '\ 0'.

La declaración en C++ 2003 es bastante vaga. Pero en C++ 0x, al contar la longitud de la cadena, la cadena ancha literal wchar_t se tratará igual que char32_t, y diferente de char16_t.

Hay un mensaje que indica claramente cómo las ventanas wchar_t implementa en https://stackoverflow.com/questions/402283?tab=votes%23tab-top

En resumen, wchar_t en las ventanas es 16bits y codificado con UTF-16. La declaración en estándar aparentemente deja algo conflictivo en Windows.

por ejemplo,

wchar_t kk[] = L"\U000E0005"; 

Esto supera 16bits y para UTF-16 que necesita dos 16 bits para codificar (un par suplente).

Sin embargo, desde el estándar, kk es una matriz de 2 wchar_t (1 para el nombre universal \ U000E005, 1 para \ 0).

Pero en el almacenamiento interno, Windows necesita 3 objetos wchar_t de 16 bits para almacenarlo, 2 wchar_t para el par suplente y 1 wchar_t para el \ 0. Por lo tanto, a partir de la definición de la matriz, kk es una matriz de 3 wchar_t.

Aparentemente es incompatible entre sí.

Creo que la solución más simple para Windows es "prohibir" cualquier cosa que requiera un par suplente en wchar_t ("prohibir" cualquier unicode fuera de BMP).

¿Hay algún problema con mi comprensión?

Gracias.

Respuesta

3

El estándar requiere que wchar_t sea lo suficientemente grande como para contener cualquier carácter en el conjunto de caracteres admitidos.En base a esto, creo que su premisa es correcta: es incorrecto que VC++ represente el carácter único \U000E0005 utilizando dos unidades wchar_t.

Caracteres fuera del BMP rara vez se utilizan, y Windows mismo internamente utiliza la codificación UTF-16, por lo que es simplemente conveniente (incluso si es incorrecto) para que VC++ se comporte de esta manera. Sin embargo, en lugar de "prohibir" tales caracteres, es probable que el tamaño de wchar_t aumente en el futuro, mientras que char16_t toma su lugar en la API de Windows.

La respuesta se conectó a un tanto engañoso, así:

En Linux, un wchar_t es de 4 bytes, mientras que en Windows, que es de 2 bytes

El tamaño de wchar_t depende únicamente en el compilador y no tiene nada que ver con el sistema operativo. Simplemente sucede que VC++ usa 2 bytes para wchar_t, pero una vez más, esto podría cambiar en el futuro.

+0

gracias. lo entiendo ahora. En algún momento es difícil entender un nuevo concepto, pero una vez que lo tienes, se vuelve más simple al instante. – user534498

+0

Windows técnicamente usa 'WCHAR', no' wchar_t'. Se ha defraudado como 'unsigned short' en el pasado y podría convertirse en' char16_t' en el futuro. Pero, sinceramente, no veo que eso suceda, los literales de cadenas se romperían. – MSalters

+0

@MSalters: ¿Por qué se romperían los literales de cadena? Para eso están las macros 'TEXT (" ... ")', nunca se suponía que las personas usaran literales en bruto 'L' ... ''. Además, al menos en VS2005, 'WCHAR' es un tipodef para' wchar_t', no 'unsigned short'. – casablanca

1

Windows no sabe nada de wchar_t, porque wchar_t es un concepto de programación. Por el contrario, wchar_t es solo almacenamiento y no sabe nada sobre el valor semántico de los datos almacenados en él (es decir, no sabe nada de Unicode o ASCII o lo que sea).

Si un compilador o SDK que se dirige a Windows define wchar_t para ser 16 bits, entonces ese compilador puede estar en conflicto con el estándar de C++ 0x. (No sé si hay algunas cláusulas de salida que permitan que wchar_t sea de 16 bits). Pero en cualquier caso, el compilador podría definir que wchar_t sea de 32 bits (para cumplir con el estándar) y proporcionar funciones de tiempo de ejecución para convertir a/de UTF-16 para cuando necesitas pasar tu wchar_t * a las API de Windows.

Cuestiones relacionadas