ascii碼_C語言到底使用什麼編碼?誰說C語言使用ASCII碼,真是荒謬!
阿新 • • 發佈:2020-12-17
技術標籤:ascii碼c語言unicodec語言中文網c語言計算程式執行時間delphi 中文轉 ascii編碼gbk編碼線上轉換
C語言是 70 年代的產物,那個時候只有 ASCII,各個國家的字元編碼都還未成熟,所以C語言不可能從底層支援 GB2312、GBK、Big5、Shift-JIS 等國家編碼,也不可能支援 Unicode 字符集。稍微有點C語言基本功的讀者可能認為C語言使用 ASCII 編碼,字元在儲存時會轉換成對應的 ASCII 碼值,這也是錯誤的,你被大學老師和教材誤導了!在C語言中,只有 char 型別的窄字元才使用 ASCII 編碼,char 型別的窄字串、wchar_t 型別的寬字元和寬字串都不使用 ASCII 編碼!wchar_t 型別的寬字元和寬字串使用 UTF-16 或者 UTF-32 編碼,這個在上節已經講到了,現在只剩下 char 型別的窄字串(下面稱為窄字串)沒有講了,這就是本節的重點。對於窄字串,C語言並沒有規定使用哪一種特定的編碼,只要選用的編碼能夠適應當前的環境即可,所以,窄字串的編碼與作業系統和編譯器有關。但是,可以肯定的說,在現代計算機中,窄字串已經不再使用 ASCII 編碼了,因為 ASCII 編碼只能顯示字母、數字等英文字元,對漢語、日語、韓語等其它地區的字元無能為力。討論窄字串的編碼要從以下兩個方面下手。原始檔使用什麼編碼
原始檔用來儲存我們編寫的程式碼,它最終會被儲存到本地硬碟,或者遠端伺服器,這個時候就要儘量壓縮檔案體積,以節省硬碟空間或者網路流量,而程式碼中大部分的字元都是 ASCII 編碼中的字元,用一個位元組足以容納,所以 UTF-8 編碼是一個不錯的選擇。UTF-8 相容 ASCII,程式碼中的大部分字元可以用一個位元組儲存;另外 UTF-8 基於 Unicode,支援全世界的字元,我們編寫的程式碼可以給全球的程式設計師使用,真正做到技術無國界。常見的 IDE 或者編輯器,例如 Xcode、Sublime Text、Gedit、Vim 等,在建立原始檔時一般也預設使用 UTF-8 編碼。但是 Visual Studio 是個奇葩,它預設使用本地編碼來建立原始檔。
所謂本地編碼,就是像 GBK、Big5、Shift-JIS 等這樣的國家編碼(地區編碼);針對不同國家發行的作業系統,預設的本地編碼一般不同。簡體中文字的 Windows 預設的本地編碼是 GBK。
對於編譯器來說,它往往支援多種編碼格式的原始檔。微軟編譯器、GCC、LLVM/Clang(內嵌於 Xcode 中)都支援 UTF-8 和本地編碼的原始檔,不過微軟編譯器還支援 UTF-16 編碼的原始檔。如果考慮到原始檔的通用性,就只能使用 UTF-8 和本地編碼了。
窄字串使用什麼編碼
前面講到,用 puts 或者 printf 可以輸出窄字串,程式碼如下:
#include int main(){ puts("C語言中文網"); printf("http://c.biancheng.net"); return 0;}
"C語言中文網"
和
"http://c.biancheng.net"
就是需要被處理的窄字串,程式執行後,它們會被載入到記憶體中。你看,這裡面還包含了中文,肯定不能使用 ASCII 編碼了。
1) 微軟編譯器使用本地編碼來儲存這些字元。不同地區的 Windows 版本預設的本地編碼不一樣,所以,同樣的窄字串在不同的 Windows 版本下使用的編碼也不一樣。對於簡體中文版的 Windows,使用的是 GBK 編碼。2) GCC、LLVM/Clang 編譯器使用和原始檔相同的編碼來儲存這些字元:如果原始檔使用的是 UTF-8 編碼,那麼這些字元也使用 UTF-8 編碼;如果原始檔使用的是 GBK 編碼,那麼這些字元也使用 GBK 編碼。你看,對於程式碼中需要被處理的窄字串,不同的編譯器差別還是挺大的。不過可以肯定的是,這些字元始終都使用窄字元(多位元組字元)編碼。正是由於這些字元使用 UTF-8、GBK 等編碼,而不是使用 ASCII 編碼,所以它們才能包含中文。那麼,為什麼很多初學者會誤認為C語言使用 ASCII 編碼呢?不管是在課堂跟著老師學習,還是通過網際網路自學,初學者都是從處理英文開始的,對於英文來說,使用 GBK、UTF-8、ASCII 都是一樣的,GBK、UTF-8 都相容 ASCII,初學者根本察覺不出用了哪種編碼。另外,很多大學老師和書籍作者也經常會念叨,字元在儲存時會被轉換成對應的 ASCII 碼,在讀取時又會從 ASCII 碼轉換成對應的字元實體,大家需要熟悉 ASCII 編碼,它是C語言處理字元的基礎,這從很大程度上給初學者造成一種錯誤印象:C語言和 ASCII 編碼是繫結的,C語言使用 ASCII 編碼。
總結
對於 char 型別的窄字元,始終使用 ASCII 編碼。對於 wchar_t 型別的寬字元和寬字串,使用 UTF-16 或者 UTF-32 編碼,它們都是基於 Unicode 字符集的。對於 char 型別的窄字串,微軟編譯器使用本地編碼,GCC、LLVM/Clang 使用和原始檔編碼相同的編碼。另外,處理窄字元和處理寬字元使用的函式也不一樣:
- 標頭檔案中的 putchar、puts、printf 函式只能用來處理窄字元;
- 標頭檔案中的 putwchar、wprintf 函式只能用來處理寬字元。