Windows下c++字符編碼(一)

字符編碼基礎

在談c++之前,不得不先來說說各種字符編碼。我們知道最早的英文字符采用ascii,因爲英文字符很少,因此一個char就夠用了。但是由於處理其他語言的需求,8位的char顯然不夠用,這就要求更多位數的編碼。

GBK和ANSI

在中國,我們的國標是GBK,(準確的說經歷了GB2313->GBK->GB18030的發展過程),我們常說的漢字佔兩個字節也就是來源於此。

微軟作爲一個世界大廠,採用什麼編碼呢?微軟雖然在語言支持上很上心,不過編碼卻很混亂,微軟的默認編碼是ANSI,這是個什麼東西呢?這其實就是大雜燴,英文還是ascii,中文是GBK,港澳臺使用它們那邊的Big5……等等。這些編碼並不統一,是非常沒有兼容性的。其實ANSI不是一種編碼,不過我就這麼簡單的說了,關於ANSI具體是什麼,你可以看看這篇文章:https://www.cnblogs.com/malecrab/p/5300486.html

由於我們主要還是說中文問題,以下提到ANSI的地方,你應該立即聯想到,中文是採用GBK編碼的。其中,值得一提的是GBK編碼是雙字節的,這是中文字符佔兩個字節說法的由來。

Unicode

由於各地編碼的不統一,於是產生了Unicode,Unicode其實是一個標準,而不是一種編碼。Unicode現有兩套標準,ucs2和ucs4,一開始認爲雙字節夠用,就是ucs2,後來發現雙字節不夠用,那就擴展到4字節吧,於是就有了ucs4。Unicode現在主要有三種實現方式。即utf-8,utf-16,和utf-32。

utf-16

先講utf-16,這是採用雙字節表示的,遵從ucs2。在存儲時,按兩個字節的排布順序,可以分爲UTF-16LE(Little Endian,小端字節序)和UTF-16BE(Big Endian,大端字節序),微軟所說的Unicode默認就是 UTF-16LE。注意微軟後來也搞了Unicode,但是微軟自己鼓吹的Unicode只是其中一種實現方式而已。

utf-16後來發現雙字節不夠用,於是增加了採用一對雙字節來表示一個字符,這其中也包括一些生僻漢字,之後我們將會提到具體例子。所以其實標準的utf-16也是變字長的編碼,很多人認爲utf-16編碼是定長編碼,這其實是錯誤的。此外,utf-16不等價於ucs2,可以認爲ucs2是定長編碼(雙字節),而utf-16是ucs2的擴展。

utf-32

再說utf-32,既然雙字節不夠用,那就用四字節吧,於是就有了ucs4標準和utf-32實現方式。utf-32所有的字符都採用4個字節,這纔是真正的定長編碼。utf-32等價於ucs4,utf-32也存在存儲順序的問題。由於utf-32基本沒人用,就不詳細展開。

不過,我們知道代碼源文件還是ascii字符主導。而在網頁上,大量的標記都是ascii字符。utf-32要用4字節,utf-16也要2字節,都比最初的ascii長,這顯然是非常浪費空間的,更何況網絡傳輸數據越少越好,因此utf-16和utf-32都是不合用的。

utf-8

utf-8解決了這個問題,utf-8是完全的變長編碼,兼容ascii,也就是ascii編碼部分保留,其他的字符根據情況有2,3,4字節。其中特別值得注意的是漢字一般是三個字節,也有四個字節的生僻字情況。(如果你擁護utf-8的話,請不要在說漢字佔2字節這樣的傻話了。)

utf-8是Unix/Linux系統的默認編碼,在這些系統上使用charstring,無論輸入輸出都是使用utf-8,因此一般不必擔心編碼問題。在這些系統上,string = "你好世界"size()是12,也就是一個字符三個字節,是沒有任何問題的。你編輯c++源代碼基本不必擔心編碼問題。

但是在windows下就很複雜了。windows自帶Notepad是默認ANSI編碼的。Notepad++和VS Code是默認utf-8編碼,未經配置的gvim以及visual studio默認也是ANSI。關於c++源代碼寫中文的注意事項,將在之後的文章中詳細說明。

總結

現在我們來總結一下編碼我們提到的編碼知識:

  • Unicode是編碼規範而不是編碼方式,它有兩個標準,主要有三種實現方式。

  • utf-8和utf-16都是變長編碼,只有utf-32是定長編碼。

  • 網頁上基本採用utf-8作爲編碼方式,utf-32基本很難用到。

  • 微軟系統採用的ANSI默認編碼,兼容ascii,其中文采用GBK編碼,漢字爲雙字節,兼容性不好。

  • 微軟也有Unicode,它使用的Unicode是utf-16,不兼容ascii,中文爲雙字節,少數爲4字節。

  • Unix/Linux採用utf-8變長編碼,兼容ascii,其中中文一般爲3字節,少數4字節。

建議

現在我們來討論c++的字符編碼問題。

在Unix/Linux系統下,我建議一律採用utf-8編碼,一般沒有任何問題。不過值得注意的一點是此係統下,wchat_twstring表示的字符是4字節的字符,應該就是utf-32了。然而utf-32除了定長這一特點之外,沒有任何好處,太浪費空間,用處很少,沒必要去碰它。不過wstring的問題我們之後還會討論,你將會了解更多。

在Windows下,如果你不得不在源文件寫中文,而且又不想看我之後幾篇又臭又長的詳解,你可以使用Qt專有的QString,或者使用Visual Studio來寫代碼。前者的的默認編碼是utf-16,如果不用生僻字,甚至可以按照定長編碼的方式處理字符。後者是依靠微軟這個IDE強大的功能,可以處理各種編碼的源文件。

如果你還想了解更多工作原理,請看之後的文章。我將會首先使用g++8.1.0做實驗,說明c++的字符串的一些特性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章