寬字符與Unicode (c語言 漢語字符串長度)


在C語言中,我們使用char來定義字符,占用一個字節,最多只能表示128個字符,也就是ASCII碼中的字符。計算機起源於美國,char 可以表示所有的英文字符,在以英語為母語的國家完全沒有問題。

但是世界上存在很多不同的語言,例如漢語、漢語、日語等有成千上萬個字符,需要用多個字節來表示,稱之為寬字符(Wide Character)。Unicode 是寬字符編碼的一種,已經被現代計算機指定為默認的編碼方式,Windows 2000以后的操作系統,包括Windows 2000、XP、Vista、Win7、Win8、Win10、Windows Phone、Windows Server 等(它們統稱為 Windows NT)都從底層支持Unicode,存取效率比 char 要高。

更多內容請查看:ASCII編碼與Unicode編碼

C語言中的寬字符

在C語言中,使用wchar.h頭文件中的wchar_t來定義寬字符,例如:

wchar_t ch = 'A';

wchar_t 被定義為typedef unsigned short wchar_t,和一個無符號整型一樣,占用兩個字節。

如果定義寬字符串,需要加前綴L,例如:

wchar_t *str = L"C語言中文網";

L是必須要加的,並且與字符串之間不能有空格,只有這樣編譯器才知道每個字符占用兩個字節。

寬字符示例:

  1. #include <stdio.h>
  2. #include <wchar.h>
  3. int main(){
  4. char ch = 'A';
  5. wchar_t wch = 'A';
  6. char str[] = "C語言中文網";
  7. wchar_t wstr[] = L"C語言中文網";
  8. printf("ch=%d, wch=%d, str=%d, wstr=%d\n", sizeof(ch), sizeof(wch), sizeof(str), sizeof(wstr));
  9. return 0;
  10. }

運行結果:
ch=1, wch=2, str=12, wstr=14

wstr 之所以比 str 多兩個字節是因為:字符 'C' 占用兩個字節,字符串結束標志 '\0' 也占用兩個字節。

寬字符串的長度

計算ASCII字符串長度使用 strlen 函數,計算寬字符串長度使用 wcslen 函數:

  1. #include <stdio.h>
  2. #include <wchar.h>
  3. #include <string.h>
  4. int main(){
  5. char str[] = "C語言中文網";
  6. wchar_t wstr[] = L"C語言中文網";
  7. printf("strlen(str)=%d, wcslen(wstr)=%d\n", strlen(str), wcslen(wstr));
  8. return 0;
  9. }

運行結果:
strlen(str)=11, wcslen(wstr)=6

strlen 的運行結果顯然不正確,因為它把一個字節作為一個字符計算,而 wcslen 把兩個字節作為一個字符計算。

注意:wcslen 在 string.h 和 wchar.h 頭文件中均有說明。

維護一個版本的源代碼

在 Windows NT 以前的操作系統中,甚至包括 Windows 98,對寬字符的支持都不是很好,所以大多情況下使用ASCII編碼。Windows NT 推出以后,已經從底層支持了Unicode,所以在 Windows NT 上的程序大多使用Unicode。

如果你希望程序能夠在各種版本的Windows操作系統中運行,那么就需要維護兩個版本的源代碼,ASCII 版和 Unicode 版。ASCII 字符和 Unicode 字符的定義、使用都不一樣,要想在一個版本的源代碼中做兼容處理會非常困難,要做大量的工作,對程序員來說簡直是噩夢。

不過,Windows 又為我們做了一件好事,已經處理了兼容性問題。它是怎么做到的呢?

例如對於字符串,ASCII 中使用 char 來定義,而 Unicode 中使用 wchar_t 來定義,並且需要添加前綴L。那么在 windows.h 頭文件中(或者是它包含的其他頭文件)就這樣來處理:

  1. #ifdef UNICODE
  2. typedef wchar_t TCHAR;
  3. #define TEXT(quote) L##quote
  4. #else
  5. typedef char TCHAR
  6. #define TEXT(quote) quote
  7. #endif

我們在源碼中可以這樣來使用:

TCHAR str[] = TEXT("C語言中文網");

如果是Unicode版,也就是定義了UNICODE宏,那么上面的語句等價於:

wchar_t str[] = L"C語言中文網";

如果是ASCII,也就是沒有定義UNICODE宏,那么等價於:

char str[] = "C語言中文網";

在Windows中,隨處可見這樣的處理。雖然現代操作系統都已經支持Unicode,無需再考慮與ASCII的兼容性問題,但是依然要為這些歷史問題付出代價。

總結:由於各種各樣的原因,我們優先使用Windows定義的數據類型、宏、結構體等,這樣編寫的程序兼容性較好,不用考慮ASCII和Unicode的問題。但這也帶來了一個挑戰,就是要熟悉Window定義的數據類型、宏、結構體等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM