檔案編碼和檔案內的字串字面值編碼是兩個概念

2022-03-15 17:57:36 字數 2698 閱讀 8349

我們知道,calabel的字串使用的是utf8編碼,

通常在xcode下,直接calabel *p = ...; p->settext("漢字"),顯示漢字是沒有任何問題的,

但是,在vs2013中卻顯示的是亂碼。

很多人在群裡面問了,我都答:請使用utf8編碼。

他說,我的檔案是utf8格式的啊。呵呵,沒那麼簡單好嗎,檔案編碼和字串字面值編碼是兩個概念。

vs2013的一條預編譯指令

#pragma execution_character_set("utf-8") 

這下就可以放心地在vs2013裡面p->settext("漢字"),p->settext("中文")了

由於它只是一條預編譯指令,一般將這句放在include群後面就好了

要搞清楚這個問題,先要弄明白編碼。但是編碼問題實在太複雜,這裡肯定講不開。

我先找乙個例子,比如:"中文" 的 unicode 碼點/utf8編碼/gbk 分別是多少。

先去這個**,輸入 "中文" 查詢對應的 unicode 碼點/utf8編碼:

unicode的碼點分別是(十進位制):中(20013),文(25991)。 對應的utf8編碼分別(16進製制): 中(e4b8ad),文(e69687)。

然後再去下面這個**,輸入 "中文" 查詢對應的 gbk 編碼:

gbk編碼16進製制(gbk內碼)分別是:中(d6d0),文(cec4)。

現在已經知道了"中文"的utf8和gbk編碼的具體值。 我們再看看vc2010是怎麼處理的。

// utf8 no bom

// 檔案中包含不能在當前**頁(936)中表示的字元

#include int main() 

return 0;

// output:

// 0xe4 0xb8 0xad 0xe6

}

輸出是:0xe4 0xb8 0xad 0xe6。 感覺好像是對的。

但是,先別急:vc編譯時輸出了一條警告資訊: utf8nobom.cpp : warning c4819: 該檔案包含不能在當前**頁(936)中表示的字元。 請將該檔案儲存為 unicode 格式以防止資料丟失。

潛台詞就是,你這個**有gbk不能表示的字元,請用unicode方式儲存。 vc根本就沒把 **(utf8nobom.cpp) 當作utf8,vc只是把它作為gbk處理罷了。

那為什麼又輸出了正確的結果呢?

因為 vc 把 (utf8nobom.cpp) 當作 gbk,而編譯時也要轉換為本地編碼(也是gbk)。 因此,utf8編碼的 "中文",被vc當作編碼為 "0xe4 0xb8 0xad 0xe6" 的其他中文處理了。 vc已經不知道 "0xe4 0xb8 0xad 0xe6" 是對應 "中文" 字面值了。

但是在gbk(實際是無bom的utf8)轉gbk的過程中,發現了一些utf8編碼的字元並不是 gbk能表達的合理方式,因此就出現了那個c4819編譯警告。

// utf8 with bom

#include int main() 

return 0;

// output:

// 0xd6 0xd0 0xce 0xc4

}

編譯沒有警告,但是輸出有問題:0xd6 0xd0 0xce 0xc4。

原始檔明明是 utf8 編碼的格式"0xe4 0xb8 0xad 0xe6", 怎麼變成了 "0xd6 0xd0 0xce 0xc4" (這個是gbk編碼)?

這就是vc私下幹的好事:它自作聰明的將utf8源**轉換為gbk處理了!

vc為何要做這樣蠢事?

原因是為了相容老的vc版本。 因為以前的vc不能處理utf8,都是用本地編碼處理的。

// gbk

#include int main() 

return 0;

// output:

// 0xd6 0xd0 0xce 0xc4

}

沒有編譯錯誤,輸出也和源**一致:"0xd6 0xd0 0xce 0xc4"。

因為原始檔就是gbk,cl在編譯時gbk轉化為gbk,沒有改變字串。

只是,現在很多人不想用gbk了(因為只能在中國地區用,不能表示全球字元)。

到這裡,可以初步小結一下:

vc編輯器和vc編譯器是2個概念,vc編輯器支援utf8並不能表示vc編譯器也支援utf8

vc編輯器從2008?開始支援帶bom的utf8(不帶bom的暫時沒戲,因為會本地編碼衝突)

vc編譯器從2010開始重要可以支援utf8了(雖然支援方式很不優雅)

vc2010重要增加了utf8的編譯支援(#pragma execution_character_set("utf-8")), 具體檢視:

// utf8 with bom (vc2010), 這句是重點!

#pragma execution_character_set("utf-8")

#include int main() 

return 0;

// output:

// 0xe4 0xb8 0xad 0xe6

}

沒有編譯錯誤,輸出也和源**一致:"0xe4 0xb8 0xad 0xe6"。

utf8編碼,utf8輸出。完美!

微軟在 utf-8 中使用 bom 是因為這樣可以把 utf-8 和 ascii 等編碼明確區分開。bom 位元組序列 在utf-8 其實是無意義的, 再utf-16 或者 utf-32 裡面才有意義。

**:

C 字串字面值

c 字串型別 char 和 wchar t c11 新增了 char16 t 和 char32 t 例子 wchat t title l char t w char string char16 t name u char16 char16 string char32 t car u char 32 ...

字元編碼和檔案

儲備知識點 1.計算機系統分為三層 應用程式 作業系統 計算機硬體 2.執行python程式的三個步驟 1.先啟動python直譯器 2.再將python檔案當作普通的文字檔案讀入記憶體 3.解釋執行讀入記憶體的 開始識別語法 字元編碼 1.什麼是字元編碼 字元編碼表 人類的字元 數字 1bytes...

字元編碼和檔案處理

檔案處理 應用程式任何操作硬體的請求都需要向作業系統發起系統呼叫,然後由操作做系統去操作硬體 1.開啟了編輯器就開啟了啟動了乙個程序,是在記憶體中的,所以,用編 輯器編寫的內容也都是存放與記憶體中的,斷電後資料丟失。2.要想永久儲存,需要點選儲存按鈕 編輯器把記憶體的資料刷到了硬碟 上。3.在我們編...