linux c编译 utf-8,在Linux C编程中使用Unicode和UTF-8
在Linux C編程中使用Unicode和UTF-8
目前各種Linux發行版都支持UTF-8編碼,當前系統的語言和字符編碼設置保存在一些環境變量中,可以通過locale命令查看:$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
常用漢字也都位于BMP中,所以一個漢字的存儲通常占3個字節。例如編輯一個C程序:#include int main(void)
{
printf("你好\n");
return 0;
}
源文件是以UTF-8編碼存儲的:$ od -tc nihao.c
0000000 # i n c l u d e < s t d i o .
0000020 h > \n \n i n t m a i n ( v o i
0000040 d ) \n { \n \t p r i n t f ( " 344 275
0000060 240 345 245 275 \ n " ) ; \n \t r e t u r
0000100 n 0 ; \n } \n
0000107
其中八進制的344 375 240(十六進制e4 bd a0)就是“你”的UTF-8編碼,八進制的345 245 275(十六進制e5 a5 bd)就是“好”。把它編譯成目標文件,"你好\n"這個字符串就成了這樣一串字節:e4 bd a0 e5 a5 bd 0a 00,漢字在其中仍然是UTF-8編碼的,一個漢字占3個字節,這種字符在C語言中稱為多字節字符(Multibyte Character)。運行這個程序相當于把這一串字節write到當前終端的設備文件。如果當前終端的驅動程序能夠識別UTF-8編碼就能打印出漢字,如果當前終端的驅動程序不能識別UTF-8編碼(比如一般的字符終端)就打印不出漢字。也就是說,像這種程序,識別漢字的工作既不是由C編譯器做的也不是由libc做的,C編譯器原封不動地把源文件中的UTF-8編碼復制到目標文件中,libc只是當作以0結尾的字符串原封不動地write給內核,識別漢字的工作是由終端的驅動程序做的。
但是僅有這種程度的漢字支持是不夠的,有時候我們需要在C程序中操作字符串里的字符,比如求字符串"你好\n"中有幾個漢字或字符,用strlen就不靈了,因為strlen只看結尾的0字節而不管字符串里存的是什么,求出來的是字節數7。為了在程序中操作Unicode字符,C語言定義了寬字符(Wide Character)類型wchar_t和一些庫函數。在字符常量或字符串字面值前面加一個L就表示寬字符常量或寬字符串,例如定義wchar_t c = L'你';,變量c的值就是漢字“你”的31位UCS編碼,而L"你好\n"就相當于{L'你', L'好', L'\n', 0},wcslen函數就可以取寬字符串中的字符個數。看下面的程序:#include #include int main(void)
{
if (!setlocale(LC_CTYPE, "")) {
fprintf(stderr, "Can't set the specified locale! "
"Check LANG, LC_CTYPE, LC_ALL.\n");
return 1;
}
printf("%ls", L"你好\n");
return 0;
}
寬字符串L"你好\n"在源代碼中當然還是存成UTF-8編碼的,但編譯器會把它變成4個UCS編碼0x00004f60 0x0000597d 0x0000000a 0x00000000保存在目標文件中,按小端存儲就是60 4f 00 00 7d 59 00 00 0a 00 00 00 00 00 00 00,用od命令查看目標文件應該能找到這些字節。$ gcc hihao.c
$ od -tx1 a.out
printf的%ls轉換說明表示把后面的參數按寬字符串解釋,不是見到0字節就結束,而是見到UCS編碼為0的字符才結束,但是要write到終端仍然需要以多字節編碼輸出,這樣終端驅動程序才能識別,所以printf在內部把寬字符串轉換成多字節字符串再write出去。事實上,C標準并沒有規定多字節字符必須以UTF-8編碼,也可以使用其它的多字節編碼,在運行時根據環境變量確定當前系統的編碼,所以在程序開頭需要調用setlocale獲取當前系統的編碼設置,如果當前系統是UTF-8的,printf就把UCS編碼轉換成UTF-8編碼的多字節字符串再write出去。一般來說,程序在做內部計算時通常以寬字符編碼,如果要存盤或者輸出給別的程序,或者通過網絡發給別的程序,則采用多字節編碼。
關于Unicode和UTF-8本節只介紹了最基本的概念,部分內容出自,讀者可進一步參考這篇文章。
總結
以上是生活随笔為你收集整理的linux c编译 utf-8,在Linux C编程中使用Unicode和UTF-8的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux: 多线程
- 下一篇: linux多线程实验实验报告,Linux