用萬國碼寫C++程式


首先我先給個簡單的結論
「盡量使用UTF-8,不管是在Windows還是Linux」

寬字元這個字眼泛指UTF-16以上的編碼方式(UTF-16、UTF-32等等),UTF-8不用寬字元來儲存,使用C語言原本就有的char便可。


sizeof(char)==1
sizeof(wchar_t)==2 Windows下的寬字元
sizeof(wchar_t)==4 Linux下的寬字元


使用UTF-8的情況
char *str= u8"ToyBox" u8"玩具"
sizeof(str) 7
(6個字母加結尾)
5
(兩個中文字加結尾)
strlen(str) 6
(正確)
4
(誤判了)











在UTF-8裡面,一個中文字元佔2byte以上,所以不能用strlen()來判斷字數。

※如果你在程式碼寫 L"玩具" 會當成是萬國碼寬字元
而只寫 "玩具"前面沒補上L的話會被GCC當UTF-8處理
但是 Visual Studio 是依OS語系來轉換,台灣這邊就是當成BIG5編碼了
C++11有提供新的寫法 u8"玩具" 來指定編譯器要以UTF-8處理


下面是Windows下的寬字元


Windows下的寬字元
wchar_t *str= L"ToyBox" L"玩具"
sizeof(str) 14
(每個字元都佔2byte)
6
(兩個中文字加結尾)
strlen(str) 6
(正確)
2
(正確)











上面只是個例子,萬國碼有可能一個字就超過2byte,所以連Windows下的 wchar_t都無法正確計算字數,所以如果想要讓每個字都佔有相同的大小,你必須選擇UTF-32才夠大,使用寬字元的好處就是計算字數很容易,要個別讀字碼也很輕鬆。 


UTF-8的最大好處在於它可沿用ansi key code的處理方式,像 fopen() 就不用改成 wfopen() 這怪樣子(更別說不同的編譯器可能還會有不同的名字),所以不支持萬國碼的舊版lua照樣可以接受UTF-8字串。

UTF-8有分「檔頭含BOM」跟「檔頭不含BOM」兩種
含BOM這種是微軟想出來的
不含BOM這種才是真正的UTF-8


大致上比較起來,不含BOM會是比較好的選擇,但可能是為了配合微軟,大多數場合對於含不含BOM並不在意,像是python、gcc、lua都不介意


帶有BOM的UTF-8 沒有BOM的UTF-8
缺點 1.CMake的組態檔不接受這種編碼
2.php也不吃這個
3.即使只寫英文也無法被當成ansi文件
4.NetBeans的Breadcrumbs會失效
1.這種程式碼在Visual Stduio不能除錯









最後誠心建議以UTF-8為主就好,我過去寫的程式為了兼容UTF-8跟寬字元真的多寫了很多東西,現在都以UTF-8為主,必要時才轉為寬字元。

沒有留言:

張貼留言