為什麼這篇chcp utf-8鄉民發文收入到精華區:因為在chcp utf-8這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者purpose (purpose)看板C_and_CPP標題Re: [問題] 關於中文編碼的一些...
: 4.用主控台應用程式,也就是cmd.exe來看中文字串,是不是編碼一定要改成ANSI? 用
: UTF-8是不是就一定看成亂碼?
: 答:沒這回事,不過用ANSI與UTF-8的程式不一樣
: UTF-8可能需要做一個轉換的動作
做個實驗,用 Windows XP 的記事本寫個檔案 u8.c
#include <stdio.h>
int main() {
printf("一二三\n");
return 0;
}
用記事本存檔,此時選擇編碼為UTF-8,故其中的"一"字,其儲存值將為 E4 B8 80
接下來編譯:
執行 cl.exe u8.c 得到 u8.exe 在繁體中文版 Windows XP 下的命令提示字元下執行
u8.exe,輸出字串"一二三"
執行 gcc u8.c 得到 a.exe,同樣執行之,輸出字串"銝胤몌"
這是因為編譯器的判斷兩個字串常數 "一二三" 時的差異,微軟的 cl.exe 做了私下
的轉換,使原本用 UTF-8 存的中文字變成 Big5 了。
打開命令提示字元,執行 chcp 65001 切換到 UTF-8,再執行 a.exe 即可看到正確的
中文"一二三"。(如果中文字顯示不全,把視窗最小化再重開,就會正常)
如果要避調微軟好心的自動轉換,就利用 shell code 常用到的技巧 "\x"
一樣寫個原始碼 asc.c 內容改為
#include <stdio.h>
int main() {
printf("\xE4\xB8\x80\n");
return 0;
}
存檔直接用 ANSI,反正用到的東西全部是 ASCII 無所謂用什麼格式。
此時不管用 cl.exe 還是 gcc.exe 去對 asc.c 編譯,其執行檔都會在 Big5 下顯示"銝耢
要用 chcp 65001 切換到 UTF-8 才能看到正確的中文字 "一"。
修文推薦一下延伸閱讀,由本版 JeffHung 前輩所寫
#1A2twiEe (C_and_CPP)
http://www.jeffhung.net/blog/articles/jeffhung/1114/
2010/11/12 補充:
剛剛觀察 VC 的貼心行為,有了些猜測,歸納於下。
不論你的原始碼儲存格式是 ANSI 或 UTF-8,只要該行程式碼是 printf("許");
則微軟都會貼心的幫你轉換好,使該執行檔,在該電腦預設 Codepage 下,顯示出 "許"。
大家都知道,「Big5 的許 = \xB3\x5C」且「ASCII的 '\' = \x5C」,所以 Big5 原始碼
的 "許" 對編譯器來說是 "\xB3\" 的形式,而這樣就少了 closing 雙引號。
用 gcc 會編譯失敗,但是 VC 卻能成功編譯這樣的程式碼,可見確實在送給編譯器之前,
有用 C_950.nls 查出 "許" 的內碼,並轉換為 \x 格式才送給編譯器處理。
那「UTF-8 的許 = \xE8\xA8\xB1」,對繁體中文版的 VC 來說,
即使原始碼格式是用 UTF-8 存,碰到 printf("許"); 還是會用 nls 轉換成「\xB3\x5C」
,也就是說,其執行檔也一樣會在 chcp 950 下的命令提示字元印出 "許"。
而 gcc 總是會依照你餵給他的原始碼內碼,直接丟去處理,因此 Big 5 原始碼的 "許"
會編譯失敗;UTF-8 原始碼的 "許" 需要先 chcp 65001 才能在命令提示字元印出 "許"。
補充說明的,大部分的編譯器都能自動判斷出純文字檔是否使用 UTF-8 格式,但微軟有
比較弱,所以微軟是強制規定:如果你用 UTF-8 當編碼,那就必須加上 UTF-8 BOM。
微軟 VC 編譯器,會用 GetACP() 得到的機碼值 (得到的 Codepage,通常是 C950) 去處
理「沒有加 BOM 的 UTF-8 原始碼檔案」,然後哭著跟你說:
warning C4819: 檔案含有無法在目前字碼頁 (950) 中表示的字元。
請以 Unicode 格式儲存檔案以防止資料遺失
重點是該原始碼,本來就已經是 Unicode 格式了,只是微軟自己弱而已。
對 gcc 來說,UTF-8 格式的原始碼有無 BOM 都能得到一樣的正確結果。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 124.8.143.116