我在cpp里寫一段中文字元串常量,它是什麼編碼的?

我在cpp里寫一段中文字元串常量,它是什麼編碼的?

例如:

#include &

using namespace std;

//一個很簡單的函數判斷x是否是utf8編碼的
void fun( const char* x )
{
int counter = 0;
for( const char* p = x; *p != ; ++p ) ++counter;
if( counter == 14 ) cout &<&< "GBK" &<&< endl; else cout &<&< "UTF8" &<&< endl; } int main() { const char x[] = "我就是要寫中文"; //請問x內部是什麼編碼? fun( x ); system( "PAUSE" ); }

網上有種說法是源代碼文件是什麼編碼,這段內容就是什麼編碼,我覺得這沒有道理,如果是這樣的話那我的文件如果是utf32的難道x也已utf32來保存嗎.

然而我試了無論怎麼改源文件的編碼,GBK也好UTF8也好甚至UTF16的也罷,vs 2017下還是會使用GBK來編碼. 請問這是為什麼?


標準有兩個概念「源字符集」和「執行字符集」。窄字元串字面量和 L 字元串字面量的執行字符集是實現定義的。源字符集也是實現定義的。

但 u8/u/U 字元串字面量的執行字符集必須是 UTF-8/UTF-16/UTF-32 。

( L 在 Windows 上是 UTF-16 , Linux 上是 UTF-32 )

譬如 MSVC 根據 BOM 、代碼頁或編譯選項確定源字符集,用當前代碼頁或編譯選項確定執行字符集。

編譯器通過源字符集將源碼轉換成內部處理的數據,然後通過執行字符集將內部處理數據變成程序實際載入的內存數據。


補充一下 @vczh 的回答,對於 Visual C++,默認走系統的 code page。

但是在 Visual C++ 2015 Update 2 中,可以顯式指定編碼。詳情參考 New Options for Managing Character Sets in the Microsoft C/C++ Compiler


除非你指定了u8,u,U之類的前綴,這些前綴會強制字元串使用utf8,utf16,utf32編碼,其他情況下,你的文件保存成什麼編碼,它就是什麼編碼


代碼中是使用了一個普通的字元串字面量初始化一個 const char 數組。

標準規定什麼前綴都沒有的字元串字面量表示一個窄字元(相對於寬字元)多位元組字元串,它的編碼是 implementation-defined,是由編譯器自己決定的。

唯一需要注意的是文件里是什麼編碼跟編譯完以後二進位中的編碼沒有關係,字元串字面量跟其他代碼一樣都是要經過編譯器的處理的。標準規定在翻譯階段 5(預處理後)將所有字元串常量和字元常量從源碼字符集轉換到執行字符集(execution character set),一些編譯器能夠通過編譯選項指定這些字面量的編碼。


如果是VC++的話,你當前用戶的code page是什麼,他就用什麼編碼。


其實這是編譯器行為,也只能用具體的編譯器解釋。當然msvc和gcc都有source charset和execution charset。

Reference:

-source-charset (Set Source Character Set) // MSVC

【轉】gcc中的-finput-charset和-fexec-charset開關 - sincoder // gcc


如果不用-source-charset[2]指定源碼字元編碼[1]的話,VisualStudio會做一些檢測來看字元編碼,如果檢測失敗,就用當前代碼頁來做編碼。

  1. Working with Strings
  2. -source-charset (Set Source Character Set)


你用utf保存,char是根據系統代碼頁來編碼的。你可在保存選項里改為big5,這種地區性ascii編碼出來的就是原樣。

拋棄char,擁抱wchar。


推薦閱讀:

泛型和反射都必須依賴運行時嗎?
offer比較:C++職位和golang職位?
請問在c++11之前,有什麼方法可以實現可變參的函數模板呢?
現代C++核心指導中提到的 span<T> 類型到底是哪個?
C++ 為什麼有時候必須額外寫 template?

TAG:編程 | C編程語言 | C | CC | WindowsAPI |