[問題] gcc對非英文data c-string採什麼編碼方式?

看板C_and_CPP作者 (問號)時間9年前 (2015/02/15 10:50), 9年前編輯推噓3(3038)
留言41則, 6人參與, 最新討論串1/1
開發平台(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

02/15 11:05, , 1F
e9 9b bb e8 85 a6 那是 UTF-8 編碼
02/15 11:05, 1F

02/15 11:11, , 2F
為何utf-8編中文要用到3個byte,2個不就夠了?
02/15 11:11, 2F

02/15 11:12, , 3F
02/15 11:12, 3F

02/15 11:15, , 4F
UTF-8 採用可變長度的編碼,多數字元都是 3 個byte
02/15 11:15, 4F

02/15 11:20, , 5F
如果編中文兩個就夠了,那請問日文跟韓文要用幾個 byte
02/15 11:20, 5F

02/15 11:23, , 6F
從另一個角度想就很清楚,到底要幾個 byte 才擺的下
02/15 11:23, 6F

02/15 11:31, , 7F
了解了,有太多語言要放
02/15 11:31, 7F

02/15 15:34, , 8F
要看你儲存文件的編碼吧?
02/15 15:34, 8F

02/15 16:24, , 9F
不對吧 source code的編碼只影響編譯器要如何讀檔
02/15 16:24, 9F

02/15 16:25, , 10F
我上面實驗扔給msvc的已經是utf-8檔 還是編出big5阿
02/15 16:25, 10F

02/15 16:27, , 11F
可以傳參數給編譯器指定string literal要用什麼編碼
02/15 16:27, 11F

02/15 16:29, , 12F
上面那些是預設情形下的編碼方式
02/15 16:29, 12F

02/15 17:29, , 13F
sorry, my fault。剛在外面隨手回錯了XD
02/15 17:29, 13F

02/15 17:30, , 14F
以 GCC 來說,會用 iconv 轉成 -fexec-charset 指定的
02/15 17:30, 14F

02/15 17:33, , 15F
看存檔編碼的是 -finput-charset
02/15 17:33, 15F

02/15 18:25, , 16F
utf-8會採3 bytes的原因會錯意了 應該說是為了能夠
02/15 18:25, 16F

02/15 18:33, , 17F
直接相容於ASCII 讓一些比較短的bit pattern被廢棄
02/15 18:33, 17F

02/15 18:33, , 18F
不能用
02/15 18:33, 18F

02/15 18:40, , 19F
這是其中一個原因,但是 2 byte 無法塞下全部也是事實
02/15 18:40, 19F

02/15 19:09, , 20F
常見的 gb2312 cp950 設計上也都是相容於 ASCII 編碼
02/15 19:09, 20F

02/15 19:32, , 21F
Unicode 規劃時至少收納了十萬個字,但常用卻沒這麼多
02/15 19:32, 21F

02/15 19:33, , 22F
因此 Windows 對於 wchar_t 使用 UCS-2 只有 2 bytes
02/15 19:33, 22F

02/15 19:33, , 23F
但在 Linux 或者 Mac 上,sizeof(wchar_t) 是 4 bytes
02/15 19:33, 23F

02/15 19:34, , 24F
則是屬於 UCS-4 的範圍。UTF-8 透過變動長度的方式
02/15 19:34, 24F

02/15 19:35, , 25F
除了基本相容於 ASCII,還要能表示 Unicode 的任何字元
02/15 19:35, 25F

02/15 20:31, , 26F
謝謝 對unicode有進一步了解了我今天才知道對中文來
02/15 20:31, 26F

02/15 20:31, , 27F
UTF-16存起來會比UTF-8小
02/15 20:31, 27F

02/15 20:36, , 28F
UTF-8 也只有保證「目前」可以表示所有 Unicode 字元 XD
02/15 20:36, 28F

02/15 20:38, , 29F
尤其現在的 UTF-8 規範把上限下修到 4 bytes, 總有一天
02/15 20:38, 29F

02/15 20:38, , 30F
還是會用完, 到時候再看看他們打算怎麼辦
02/15 20:38, 30F

02/15 20:50, , 31F
UTF-8 4bytes可以表示到U+10FFFF (17 * 2^16 = 1114112)
02/15 20:50, 31F

02/15 20:51, , 32F
Unicode 7.0也才定義113021個codepoints 要用完應該還很久XD
02/15 20:51, 32F

02/15 20:55, , 33F
就算17個planes真的用完 UTF8照規律也可以延伸到使用5 bytes
02/15 20:55, 33F

02/15 21:09, , 34F
順帶一提 這code在真的linux上跑會runtime error
02/15 21:09, 34F

02/15 21:10, , 35F
linux上uintmax_t沒有比wchar_t大
02/15 21:10, 35F

02/15 21:17, , 36F
UTF-8 下修的原因是 Unicode 本來就定到 U+10FFFF 而已
02/15 21:17, 36F

02/15 21:18, , 37F
UTF-8 4byte 其實可以表示到 0x1FFFFF (32*2^16-1=2097151)
02/15 21:18, 37F

02/15 21:18, , 38F
而 Unicode 只定到那裡的原因是 UTF-16 的 surrogate pairs
02/15 21:18, 38F

02/15 21:19, , 39F
surrogate pairs 的最後一個組合 U+DBFF U+DFFF 表示的
02/15 21:19, 39F

02/15 21:19, , 40F
就是 U+10FFFF 再上去的話 surrogate pairs 就不夠了
02/15 21:19, 40F

02/15 21:56, , 41F
那是 UTF-16 的上限, Unicode code point 是無極限的
02/15 21:56, 41F
文章代碼(AID): #1Ku0b_sE (C_and_CPP)