Re: [問題] 關於中文編碼的一些問題

看板C_and_CPP作者 (purpose)時間13年前 (2010/11/06 23:09), 編輯推噓8(804)
留言12則, 9人參與, 最新討論串2/2 (看更多)
: 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

11/06 23:18, , 1F
推推
11/06 23:18, 1F

11/06 23:18, , 2F
推推
11/06 23:18, 2F

11/06 23:32, , 3F
推推推,第一次看到chcp這個東西
11/06 23:32, 3F

11/06 23:35, , 4F
推推推推,shellcode 好黑XD
11/06 23:35, 4F
※ 編輯: purpose 來自: 124.8.143.116 (11/06 23:41)

11/06 23:55, , 5F
有\u就省事多了...
11/06 23:55, 5F

11/06 23:56, , 6F
推一個
11/06 23:56, 6F

11/08 18:51, , 7F
推推推 超黑的shellcode XD
11/08 18:51, 7F
※ 編輯: purpose 來自: 124.8.131.209 (11/12 12:24)

11/12 12:28, , 8F
gcc 因為在很多平台運行,所以應該不太可能像微軟那樣,去
11/12 12:28, 8F

11/12 12:28, , 9F
用個 nls 檔,再根據你電腦的編碼做貼心轉換處理。
11/12 12:28, 9F

11/12 12:29, , 10F
因此最保險做法,還是 JeffHung 文章說的,用 ASCII 就好
11/12 12:29, 10F
※ 編輯: purpose 來自: 124.8.131.209 (11/12 12:34)

11/15 18:39, , 11F
11/15 18:39, 11F

11/20 11:48, , 12F
ANSI C 當初是說盡量不要把非 ASCII 的東西塞入程式碼_A_
11/20 11:48, 12F
文章代碼(AID): #1CrM-xz8 (C_and_CPP)
文章代碼(AID): #1CrM-xz8 (C_and_CPP)