2012-07-16 26 views
5

Tôi đã gặp phải một vấn đề thú vị trên Windows 8. Tôi đã thử nghiệm Tôi có thể đại diện cho các ký tự Unicode được ra khỏi BMP với chuỗi wchar_t *. Các mã kiểm tra sau sản xuất kết quả bất ngờ đối với tôi:Kích thước của wchar_t * cho cặp thay thế (Unicode ký tự trong BMP) trên 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? 

U + 2008a là Han character, đó là ra khỏi nhị phân đa ngôn ngữ Pane, vì vậy nó cần được đại diện bởi một cặp thay thế trong UTF-16. Có nghĩa là - nếu tôi hiểu nó một cách chính xác - rằng nó phải được đại diện bởi hai nhân vật wchar_t. Vì vậy, tôi mong đợi sizeof (s2) là 6 (4 cho hai wchar_t-s của cặp thay thế và 2 cho kết thúc \ 0).

Vậy tại sao sizeof (s2) == 4? Tôi đã kiểm tra chuỗi s2 đã được xây dựng chính xác, bởi vì tôi đã kết xuất nó với DirectWrite và ký tự Hán đã được hiển thị chính xác.

CẬP NHẬT: Như Naveen đã chỉ ra, tôi đã cố xác định kích thước của các mảng không chính xác. Đoạn mã dưới đây tạo ra kết quả chính xác:

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. 

Trả lời

8

sizeof(s2) trả về số byte cần thiết để lưu trữ các con trỏ s2 hoặc bất kỳ con trỏ khác, đó là 4 byte trên hệ thống của bạn. Nó không liên quan gì đến (các) ký tự được lưu trữ trong được trỏ đến bởi s2.

+0

Đúng tất nhiên, cảm ơn. Sry cho câu hỏi ngu ngốc ... –

+0

"Nó không có gì để làm với các ký tự được lưu trữ trong s2" - Kể từ khi câu hỏi được gây ra bởi sự hiểu lầm giữa con trỏ và những điều chỉ ra, bạn nên tránh gây ra một sự hiểu lầm như thế. Không có ký tự được lưu trữ trong s2. Trong trường hợp này, có một ký tự được lưu trữ trong s2 [0] và s2 [1]. Nếu nó không phải là một cặp thay thế thì sẽ có một ký tự được lưu trữ trong s2 [0] một mình, tức là trong * s2. –

+0

@Windowsprogrammer: Đã sửa lỗi. –

4

sizeof(wchar_t*) giống với sizeof(void*), nói cách khác là kích thước của con trỏ. Điều đó sẽ luôn luôn 4 trên một hệ thống 32-bit, và 8 trên một hệ thống 64-bit. Bạn cần phải sử dụng wcslen() hoặc lstrlenW() thay vì 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 *) giống như sizeof (void *)" - Đó không phải là sự hiểu biết của tôi. sizeof (char *), sizeof (ký char *) và sizeof (unsigned char *) đều có cùng kích thước với sizeof (void *). sizeof (wchar_t *) và sizeof (các công cụ ngẫu nhiên khác) có thể nhỏ hơn sizeof (void *) tùy thuộc vào việc triển khai. –

+0

@Windowsprogrammer: Đúng - mặc dù phần lớn các trình biên dịch hiện đại làm cho tất cả các loại con trỏ có cùng kích thước. –

+0

Tại sao bất kỳ trình biên dịch nào, hãy để một mình các giá trị C/C++, cho phép bất kỳ 'sizeof (kiểu con trỏ nào)' nhỏ hơn 'sizeof (void *)'? Từ quan điểm của sizeof(), một con trỏ là một con trỏ là một con trỏ, nó không quan trọng kiểu dữ liệu của nó. –

0

Phụ lục của câu trả lời.
RE: để làm sáng tỏ các đơn vị khác nhau được sử dụng trong bản cập nhật câu hỏi của i1i2, i3.

i1 giá trị của 2 là kích thước trong byte
i2 giá trị là 1 là kích thước trong wchar_t, IOW 4 byte (giả sử sizeof(wchar_t) là 4).
i3 giá trị của 2 là kích thước trong wchar_t, IOW 8 byte

Các vấn đề liên quan