看板 C_and_CPP 關於我們 聯絡資訊
開發平台(Platform): (Ex: VC++, GCC, Linux, ...) VC++(2013, x86 amd64), GCC(Cygwin64) 問題(Question): 想了解編譯器對非英文的c-string是如何編碼,所以寫了下列code, 方法是將兩個中文字"電腦"寫入程式碼,以char wchar_t兩種方式存入 執行時讓資料以hex值output,觀察編碼情形 我的問題是: g++以char儲存所編出來的碼,我找不到它是什麼編碼方式, 一個中文字佔了3個char,這是什麼? UTF-24????? 結果(Wrong Output): char wchar_t msvc2013 x86及amd64 b9 71 b8 a3 96fb 8166 (Big5 "電"0xb971 (Unicode "電"0x96fb "腦"0xb8a3) "腦"0x8166) gcc on cygwin64 e9 9b bb e8 85 a6 96fb 8166 (?????) (Unicode) 程式碼(Code):(請善用置底文網頁, 記得排版) #include <iostream> #include <sstream> #include <string> #include <cstring> #include <cwchar> #include <cstdint>//-std=c++11 using namespace std; int main() { const char *c="電腦"; const wchar_t *wcl=L"電腦"; string buffer; ostringstream oss; cout<<"--c"<<endl; for(int i=0, siz=strlen(c); i<siz; ++i) { oss.clear(); oss.str(""); oss<<hex<<static_cast<uintmax_t>( c[i] ); buffer=oss.str(); cout<<buffer.substr(buffer.length()-sizeof(char)*2, sizeof(char)*2)<<' '; } cout<<endl; cout<<"--wcl"<<endl; for(int i=0, siz=wcslen(wcl); i<siz; ++i) { oss.clear(); oss.str(""); oss<<hex<<static_cast<uintmax_t>( wcl[i] ); buffer=oss.str(); cout<<buffer.substr (buffer.length()-sizeof(wchar_t)*2,sizeof(wchar_t)*2)<<' '; } cout<<endl; return 0; } 補充說明(Supplement): -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.35.84.52 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1423968639.A.D8E.html ※ 編輯: frankhsu421 (114.35.84.52), 02/15/2015 10:52:03 ※ 編輯: frankhsu421 (114.35.84.52), 02/15/2015 10:54:26
LiloHuang: e9 9b bb e8 85 a6 那是 UTF-8 編碼 02/15 11:05
frankhsu421: 為何utf-8編中文要用到3個byte,2個不就夠了? 02/15 11:11
LiloHuang: 請詳閱 http://zh.wikipedia.org/wiki/UTF-8 02/15 11:12
LiloHuang: UTF-8 採用可變長度的編碼,多數字元都是 3 個byte 02/15 11:15
LiloHuang: 如果編中文兩個就夠了,那請問日文跟韓文要用幾個 byte 02/15 11:20
LiloHuang: 從另一個角度想就很清楚,到底要幾個 byte 才擺的下 02/15 11:23
frankhsu421: 了解了,有太多語言要放 02/15 11:31
carylorrk: 要看你儲存文件的編碼吧? 02/15 15:34
frankhsu421: 不對吧 source code的編碼只影響編譯器要如何讀檔 02/15 16:24
frankhsu421: 我上面實驗扔給msvc的已經是utf-8檔 還是編出big5阿 02/15 16:25
frankhsu421: 可以傳參數給編譯器指定string literal要用什麼編碼 02/15 16:27
frankhsu421: 上面那些是預設情形下的編碼方式 02/15 16:29
carylorrk: sorry, my fault。剛在外面隨手回錯了XD 02/15 17:29
carylorrk: 以 GCC 來說,會用 iconv 轉成 -fexec-charset 指定的 02/15 17:30
carylorrk: 看存檔編碼的是 -finput-charset 02/15 17:33
frankhsu421: utf-8會採3 bytes的原因會錯意了 應該說是為了能夠 02/15 18:25
frankhsu421: 直接相容於ASCII 讓一些比較短的bit pattern被廢棄 02/15 18:33
frankhsu421: 不能用 02/15 18:33
LiloHuang: 這是其中一個原因,但是 2 byte 無法塞下全部也是事實 02/15 18:40
LiloHuang: 常見的 gb2312 cp950 設計上也都是相容於 ASCII 編碼 02/15 19:09
LiloHuang: Unicode 規劃時至少收納了十萬個字,但常用卻沒這麼多 02/15 19:32
LiloHuang: 因此 Windows 對於 wchar_t 使用 UCS-2 只有 2 bytes 02/15 19:33
LiloHuang: 但在 Linux 或者 Mac 上,sizeof(wchar_t) 是 4 bytes 02/15 19:33
LiloHuang: 則是屬於 UCS-4 的範圍。UTF-8 透過變動長度的方式 02/15 19:34
LiloHuang: 除了基本相容於 ASCII,還要能表示 Unicode 的任何字元 02/15 19:35
frankhsu421: 謝謝 對unicode有進一步了解了我今天才知道對中文來 02/15 20:31
frankhsu421: UTF-16存起來會比UTF-8小 02/15 20:31
uranusjr: UTF-8 也只有保證「目前」可以表示所有 Unicode 字元 XD 02/15 20:36
uranusjr: 尤其現在的 UTF-8 規範把上限下修到 4 bytes, 總有一天 02/15 20:38
uranusjr: 還是會用完, 到時候再看看他們打算怎麼辦 02/15 20:38
PkmX: UTF-8 4bytes可以表示到U+10FFFF (17 * 2^16 = 1114112) 02/15 20:50
PkmX: Unicode 7.0也才定義113021個codepoints 要用完應該還很久XD 02/15 20:51
PkmX: 就算17個planes真的用完 UTF8照規律也可以延伸到使用5 bytes 02/15 20:55
frankhsu421: 順帶一提 這code在真的linux上跑會runtime error 02/15 21:09
frankhsu421: linux上uintmax_t沒有比wchar_t大 02/15 21:10
LPH66: UTF-8 下修的原因是 Unicode 本來就定到 U+10FFFF 而已 02/15 21:17
LPH66: UTF-8 4byte 其實可以表示到 0x1FFFFF (32*2^16-1=2097151) 02/15 21:18
LPH66: 而 Unicode 只定到那裡的原因是 UTF-16 的 surrogate pairs 02/15 21:18
LPH66: surrogate pairs 的最後一個組合 U+DBFF U+DFFF 表示的 02/15 21:19
LPH66: 就是 U+10FFFF 再上去的話 surrogate pairs 就不夠了 02/15 21:19
uranusjr: 那是 UTF-16 的上限, Unicode code point 是無極限的 02/15 21:56