首先我先給個簡單的結論
「盡量使用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下的寬字元
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下的寬字元
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為主,必要時才轉為寬字元。