Visual studio 与字符编码浅析
轉(zhuǎn)自:https://blog.csdn.net/liangbch/article/details/79608635
關(guān)于字符編碼
1. 西方文字的編碼。
1.1 ASCII 碼,ASCII是通用的英文字符的編碼,對(duì)于英文字符,他采用7位2進(jìn)制數(shù)來(lái)表示一個(gè)英文字符,我們知道1個(gè)byte包含8個(gè)bit,對(duì)于ASCII碼來(lái)說(shuō),最高bit為0.
1.2 ISO 8859,西方廣泛使用的編碼標(biāo)準(zhǔn)。用于西方文字,有256個(gè)碼位,前128個(gè)與ASCII標(biāo)準(zhǔn)兼容,后128個(gè)用于表示歐洲文字中的其他字母。
1.3 當(dāng)然含有其他各種各樣的編碼,這里略去不談。
2. 中文和東方文字的編碼
2.1. GB 2312-1980。
這個(gè)標(biāo)準(zhǔn)由中國(guó)國(guó)家標(biāo)準(zhǔn)總局1980年發(fā)布的。 共收入漢字6763個(gè)和非漢字圖形字符682個(gè).每個(gè)漢字由2個(gè)字節(jié)表示,第一個(gè)字節(jié)的范圍是0xa1-0xfe,第二個(gè)字節(jié)的范圍也是0xa1-0xfe,其編碼空間為94*94=8836。但實(shí)際上,并非編碼空間的每個(gè)字符都有定義。6763+682=7445<8836
2.2.GBK
GBK亦采用雙字節(jié)表示,是對(duì)GB2312的擴(kuò)充。第1個(gè)字節(jié)的范圍是0x81-0xfe,第2個(gè)字節(jié)的范圍也是0x40-0xfe,剔除 xx7F一條線,即第2個(gè)字節(jié)不能是0x7f。總計(jì)23940 個(gè)碼位,共收入漢字21003個(gè)、符號(hào)883個(gè),并提供1894個(gè)造字碼位,簡(jiǎn)、繁體字融于一庫(kù)。中文Windows3.2和蘋果OS以GB2312為基本漢字編碼.
2.3. GB18030?
GB18030 有兩個(gè)標(biāo)準(zhǔn),GB18030-2000 和GB18030-2005,可看做GBK的擴(kuò)展。標(biāo)準(zhǔn)采用單字節(jié)、雙字節(jié)和四字節(jié)三種方式對(duì)字符編碼。編碼空間更大,當(dāng)然也更復(fù)雜。
2.4.GB13000
GB13000有2個(gè)版本,為1993版和2010版. GB13000.1-1993 是1993年發(fā)布的,國(guó)際正式的叫法是ISO/IEC 10646。包含20902個(gè)漢字。這里解釋下漢字字符集。GB2312規(guī)定的6763個(gè)常用漢字可稱為漢字基本集。后期陸續(xù)增加了6個(gè)輔助集。這7個(gè)漢字集包含了所有的漢字,包括簡(jiǎn)體漢字,繁體漢字,中日韓統(tǒng)一(CJK)漢字,總共包含了大約4萬(wàn)9千個(gè)漢字,其中20902個(gè)漢字被GB13000.1-1993版定義。GB13000標(biāo)準(zhǔn)是一個(gè)宏大的標(biāo)準(zhǔn),按其定義,總編碼位置高達(dá)2,147,483,648個(gè)。
2.5.UNICODE。UNICODE是由一個(gè)多語(yǔ)言軟件制造商組成的統(tǒng)一碼聯(lián)盟制定的標(biāo)準(zhǔn),和ISO這個(gè)組織不同,這個(gè)標(biāo)準(zhǔn)試圖將不同的國(guó)家的語(yǔ)言統(tǒng)一到一個(gè)標(biāo)準(zhǔn)中。UNICODE有多種不同的編碼方式,包括UTF-8,UTF-16,UTF-32等。其中UTF-8,UTF-16最為常用。在Visual studio 中,如果宏UNICODE被定義,則字符串用UTF-16表示。對(duì)于UTF16編碼,所有的英文字符和漢字都用2個(gè)字節(jié)來(lái)表示。對(duì)于英文字符,高8位為0. 對(duì)于UTF-8編碼來(lái)說(shuō),英文字符仍用8比特表示,兼容ASCII,漢字則采用3字節(jié)來(lái)表示。
關(guān)于文本文件的格式
在中文Windows,你如果用記事本創(chuàng)建一個(gè)文件,點(diǎn)擊“另存為”菜單,你會(huì)發(fā)現(xiàn),有一個(gè)編碼選項(xiàng),可選擇編碼類型。見(jiàn)下圖
編碼類型的默認(rèn)值是ANSI,其他的選項(xiàng)為 unicode, unicode big endian和utf-8. 其中ANSI意味著英文字符用ASCII的格式存儲(chǔ),中文字符的編碼格式是GB2312。 中文windows默認(rèn)的代碼頁(yè)是936.在命令行窗口輸入命令"MODE CON CP"可顯示你的windows的代碼頁(yè)設(shè)置。因?yàn)镚B2312的代碼頁(yè)是936,所以ANSI格式的編碼即GB2312編碼。unicode意味著所有字符均使用2字節(jié)的形式來(lái)存儲(chǔ),utf-8意味著,英文字符采用1字節(jié)來(lái)存儲(chǔ),漢字采用3字節(jié)老存儲(chǔ)。對(duì)于ANSI編碼格式,文件內(nèi)容不包括格式標(biāo)識(shí)。對(duì)于其他編碼格式,文件頭部有2到3個(gè)字節(jié)的標(biāo)記。具體為:
utf8:??????頭部標(biāo)識(shí)為 0xef, 0xbb, 0xbf。
unicode :?頭部標(biāo)識(shí)為 0xff, 0xfe.??對(duì)于英文字符,第1字節(jié)為其ASCII碼。第2字節(jié)為0.
unicode big endiam :??頭部標(biāo)識(shí)為0xfe, 0xff. 對(duì)于英文字符,第1字節(jié)為0,第2字節(jié)為其ASCII碼。
Visual studio 源程序的編碼類型
Visual Stuio 2013 支持的編碼類型多達(dá)100多種。如果你點(diǎn)擊"文件"->"高級(jí)保存選項(xiàng)",你可以選擇各種各樣的編碼格式,見(jiàn)下圖。其中"UTF-8 帶簽名"指文件頭部有格式標(biāo)識(shí),"無(wú)簽名"指文件頭部沒(méi)有格式標(biāo)識(shí)。
Visual C++ 與unicode
Visual C++ 工程文件有一個(gè)很重要的屬性,字符集,可設(shè)為"使用UNICODE字符集" 或"使用多字節(jié)字符集", 當(dāng)設(shè)置為前者,工程文件中增加宏定義“_UNICODE”和"UNICODE". 當(dāng)設(shè)置為使用多字節(jié)字符集,工程文件中增加宏定義“_MBCS", 是否有UNICODE這個(gè)宏對(duì)Windows API 函數(shù)的調(diào)用有很大的影響。事實(shí)上,Win32 API實(shí)際上有兩個(gè)版本。一個(gè)版本接受MBCS字符串,另一個(gè)接受Unicode字符串。例如:其實(shí)根本沒(méi)有SetWindowText()這個(gè)API函數(shù),相反,真實(shí)的函數(shù)是SetWindowTextA()和SetWindowTextW()。后綴A表明這是MBCS函數(shù),后綴W表示這是Unicode版本的函數(shù)。當(dāng)UNICODE被定義,所有的函數(shù)并被替換成W結(jié)尾的函數(shù),否則,函數(shù)被替換成A結(jié)尾的函數(shù)。下面例子來(lái)自winuser.h中的SetWindowText()函數(shù)的聲明部分:
#ifdef UNICODE
#define SetWindowText SetWindowTextW
#else
#define SetWindowText SetWindowTextA
#endif // !UNICODE
可見(jiàn),API函數(shù)根據(jù)定義UNICODE與否決定指向Unicode版本還是MBCS版本。
“UNICODE" 不但影響Windows API 函數(shù)的調(diào)用,也影響的C++/C運(yùn)行時(shí)刻庫(kù)中部分函數(shù)的調(diào)用。實(shí)際上,關(guān)于字符串的C/C++函數(shù)也有2套版本,接收ANSI字符串格式的版本,和接收UNICODE字符串格式的版本。如printf 可接受ANSI字符串,而wprintf則接受UNICODE字符串的版本。他們的參數(shù)類型也相同,前者的字符串地址的類型是"char *",后者字符串地址的類型是"wchar_t *". 為了簡(jiǎn)化編程,即使用同樣的源代碼,編譯為使用UNICODE字符集的版本和使用使用多字節(jié)字符集的版本。VC 中定義也一個(gè)tchar.h的頭文件。當(dāng)"_UNICODE"未被定義(或_MBCS被定義)時(shí),????宏"_TCHAR" 被定義為 "char",??宏"_T"被定義為空,在編譯時(shí)被預(yù)處理移除。當(dāng)"_UNICODE"被定義時(shí),"_TCHAR" 被定為為"wchar_t", 而"_T" 則被替換為"L", "L"的作用是將后面的字符或字符串轉(zhuǎn)換成相應(yīng)的Unicode 形式。
?
下面的代碼顯示了,當(dāng)UNICODE被定義和沒(méi)有定義時(shí)。程序的行為。
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <tchar.h>
#include <locale.h>
?
void dump_buff(_TCHAR ?*buff, int len)
{
?? ?printf("buff[]=\n{");
?? ?for (int i = 0; i < len; i++)
?? ?{
#ifdef _UNICODE
?? ??? ?printf("0x%04X,", (_TUCHAR)buff[i]);
#else
?? ??? ?printf("0x%02X,", (_TUCHAR)buff[i]);
#endif
?? ?}
?? ?printf("}\n");
}
?
?
int main(int argc, char* argv[])
{
?? ?_TCHAR ?buff[20];
?? ?memset(buff, 0, sizeof(buff));
?? ?dump_buff(buff, sizeof(buff) / sizeof(_TCHAR));
?
#ifdef _UNICODE
?? ?setlocale(LC_CTYPE, "");?? ?//去掉這句,wprintf 不顯示任何輸出
?? ?wcscpy(buff, _T("你好,世界\n"));
?? ?wprintf(buff);
#else
?? ?strcpy(buff, _T("你好,世界\n"));
?? ?printf(buff);
#endif
?
?
?? ?dump_buff(buff, sizeof(buff) / sizeof(_TCHAR));
?? ?return 0;
}
當(dāng)工程的屬性設(shè)為“使用UNICODE字符集”,程序輸出如下
buff[]=
{0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x000
0,0x0000,}
你好,世界
buff[]=
{0x4F60,0x597D,0x002C,0x4E16,0x754C,0x000A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x000
0,0x0000,}
當(dāng)工程的屬性設(shè)為”使用多字節(jié)字符集”時(shí),程序輸出如下
buff[]=
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}
你好,世界
buff[]=
{0xC4,0xE3,0xBA,0xC3,0x2C,0xCA,0xC0,0xBD,0xE7,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}
值得注意的是,當(dāng)使用wprintf是,必須調(diào)用"setlocale(LC_CTYPE,"");" 否則這個(gè)函數(shù)不工作,更多的詳情,請(qǐng)參閱https://www.cnblogs.com/findumars/p/6147442.html?
編譯器對(duì)字符串的解釋
不管你的VC++源程序文件是以ANSI格式保存的,還是以UTF-8格式保存的,VC++編譯器總是把一個(gè)字符串解釋為ANSI格式的字符串。這看起來(lái)沒(méi)有問(wèn)題。但是如果你想讓你的程序跨平臺(tái),這就有問(wèn)題了。Qt 可編寫(xiě)跨平臺(tái)的代碼,即源代碼不需修改或者只做很小的調(diào)整,就可以編譯成運(yùn)行在windows,linux或者Andriod平臺(tái)上的目標(biāo)程序。如果程序需要顯示或者輸出英文以外的文字,最方便的編碼就是utf-8.??如果你的Qt 使用MinGW編譯,且將Qt工程中的源代碼文件的編碼設(shè)為UTF-8. 那么,輸出沒(méi)有問(wèn)題,也不會(huì)遭遇到亂碼問(wèn)題。但是,如果你的Qt使用Visual studio 作為編譯器.??將默認(rèn)編碼設(shè)為"UTF-8",并將"UTF-8 BOM"設(shè)為"如果編碼是UTF-8則添加"。見(jiàn)下圖。
用Qt編寫(xiě)的文件可用Visual Studio正確打開(kāi),但是在運(yùn)行時(shí)則會(huì)顯示亂碼。這是因?yàn)閂C的編譯器總是將字符串解釋為ANSI格式的字符串,即使源文件的編碼是UTF-8也不例外。但是Qt的程序需要將字符串解釋為UTF-8編碼的字符串。為此,需要在源文件開(kāi)頭添加如下編譯指示。加上這句話。Qt的程序就能正確工作了
#pragma execution_character_set("utf-8")
————————————————
?
總結(jié)
以上是生活随笔為你收集整理的Visual studio 与字符编码浅析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 初中数学分几个模块_初中数学有几部分
- 下一篇: 中学物理教学参考杂志社中学物理教学参考编