2012-07-16 21 views
5

He encontrado un problema interesante en Windows 8. Probé que puedo representar caracteres Unicode que están fuera del BMP con cadenas wchar_t *. El siguiente código de prueba produce resultados inesperados para mí:Tamaño de wchar_t * para el par suplente (carácter Unicode fuera de BMP) en Windows

const wchar_t* s1 = L"a"; 
const wchar_t* s2 = L"\U0002008A"; // The "Han" character 

int i1 = sizeof(wchar_t); // i1 == 2, the size of wchar_t on Windows. 

int i2 = sizeof(s1); // i2 == 4, because of the terminating '\0' (I guess). 
int i3 = sizeof(s2); // i3 == 4, why? 

El U + 2008A es el Han character, que está fuera del panel multilingüe binario, por lo que debe ser representado por un par suplente en UTF-16. Lo que significa, si lo entiendo correctamente, que debería estar representado por dos caracteres wchar_t. Así que esperaba que sizeof (s2) fuera 6 (4 para los dos wchar_t-s del par sustituto y 2 para el finalizador \ 0).

¿Por qué es sizeof (s2) == 4? Probé que la cadena s2 se ha construido correctamente, porque la he procesado con DirectWrite y el carácter Han se ha mostrado correctamente.

ACTUALIZACIÓN: Como señaló Naveen, traté de determinar el tamaño de las matrices incorrectamente. En el siguiente código resultado correcto:

const wchar_t* s1 = L"a"; 
const wchar_t* s2 = L"\U0002008A"; // The "Han" character 

int i1 = sizeof(wchar_t); // i1 == 2, the size of wchar_t on Windows. 

std::wstring str1 (s1); 
std::wstring str2 (s2); 

int i2 = str1.size(); // i2 == 1. 
int i3 = str2.size(); // i3 == 2, because two wchar_t characters needed for the surrogate pair. 

Respuesta

8

sizeof(s2) devuelve el número de bytes necesarios para almacenar el puntero s2 o cualquier otro puntero, que es de 4 bytes en su sistema. No tiene nada que ver con los caracteres almacenados en apuntados por s2.

+0

correcta por supuesto, gracias. Sry por la estúpida pregunta ... –

+0

"No tiene nada que ver con el personaje almacenado en s2": como la pregunta fue causada por un malentendido entre los apuntadores y las cosas señaladas, deberías evitar causar otro malentendido como ese. No hay ningún personaje almacenado en s2. En este caso, hay un personaje almacenado en s2 [0] y s2 [1]. Si no fuera un par suplente, entonces habría un carácter almacenado solo en s2 [0], es decir, en * s2. –

+0

@Windowsprogrammer: Solucionado. –

4

sizeof(wchar_t*) es lo mismo que sizeof(void*), en otras palabras, el tamaño de un puntero. Eso siempre será 4 en un sistema de 32 bits y 8 en un sistema de 64 bits. Es necesario utilizar wcslen() o lstrlenW() en lugar de sizeof():

const wchar_t* s1 = L"a"; 
const wchar_t* s2 = L"\U0002008A"; // The "Han" character 

int i1 = sizeof(wchar_t); // i1 == 2 
int i2 = wcslen(s1); // i2 == 1 
int i3 = wcslen(s2); // i3 == 2 
+0

"sizeof (wchar_t *) es lo mismo que sizeof (void *)" - Eso no es mi entendimiento. sizeof (char *), sizeof (signed char *) y sizeof (unsigned char *) son todos del mismo tamaño que sizeof (void *). sizeof (wchar_t *) y sizeof (otras cosas aleatorias) pueden ser más pequeños que sizeof (void *) dependiendo de la implementación. –

+0

@Windowsprogrammer: Correcto, aunque la gran mayoría de los compiladores modernos hacen que todos los tipos de puntero tengan el mismo tamaño. –

+0

¿Por qué un compilador, y menos los estándares C/C++, permiten que cualquier 'sizeof (cualquier tipo de puntero)' sea más pequeño que 'sizeof (void *)'? Desde la perspectiva de sizeof(), un puntero es un puntero es un puntero, no importa su tipo de datos. –

0

Anexo a las respuestas.
RE: para desentrañar las diferentes unidades utilizadas en la actualización de la pregunta por i1 y i2, i3.

i1 valor de 2 es el tamaño en bytes
i2 valor de 1 es el tamaño en wchar_t, IOW 4 bytes (suponiendo sizeof(wchar_t) es 4).
i3 valor de 2 es el tamaño en wchar_t, IOW 8 bytes

Cuestiones relacionadas