長期以來,很多人都清楚,一旦C++源碼中直接使用了中文,這樣的源碼想要跨平臺(tái)(I18N)會(huì)非常困難。
創(chuàng)新互聯(lián)從2013年成立,先為尖草坪等服務(wù)建站,尖草坪等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為尖草坪企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
隨著:
Windows下:MSVC2010成為主流
Linux下:GCC升級(jí)到4.6
C++中的中文問題 才算有了一個(gè)比較優(yōu)雅的、跨平臺(tái)的Workaround。
(本文討論編譯器范圍:GCC4.6+, MSVC2010sp1+ 。本文屬于QString系列,但暫不涉及QString)
要在C++中正確使用中文,必須要了解下面兩個(gè)概念:
源碼字符集(the source character set) | 源碼文件是使用何種編碼保存的 |
執(zhí)行字符集(the execution character set) | 可執(zhí)行程序內(nèi)保存的是何種編碼(程序執(zhí)行時(shí)內(nèi)存中字符串編碼) |
C++98的問題: 既沒有規(guī)定源碼字符集,也沒有規(guī)定執(zhí)行字符集
這個(gè)... 如何理解?不妨看個(gè)例子
這個(gè)要求高么?
一個(gè)簡單的C++程序,只是希望它能在簡體中文Windows、正體中文Windows、英文版Windows、Linux、MAC OS...下的結(jié)果一致。
//main.cppint main(){ char mystr[] = "老老實(shí)實(shí)的學(xué)問,來不得半點(diǎn)馬虎"; return sizeof mystr;}
可以試著反問自己兩個(gè)問題
這個(gè)源碼文件是何種編碼保存的?(有確定答案么?)
mystr中是什么內(nèi)容?(有確定答案么?)
對(duì)C++來說,這兩個(gè)都不確定。
固定平臺(tái)的話,還能忍忍
要跨平臺(tái)的話,這種東西...
在GCC下,這兩個(gè)都可以使用你自己喜好的編碼(如果不指定,默認(rèn)都是UTF8)
-finput-charset=charset-fexec-charset=charset
除了前兩個(gè)選項(xiàng)外,還有一個(gè):
-fwide-exec-charset=charset
wide? 不妨先猜一下它是干嘛的
MSVC沒有類似前面的選項(xiàng)。
源碼字符集如何解決? | 有BOM么,有則按BOM解釋,無則使用本地Locale字符集(隨系統(tǒng)設(shè)置而變) |
執(zhí)行字符集如何解決? | 使用本地Locale字符集(隨系統(tǒng)設(shè)置而變) |
挺霸道哈(當(dāng)然,源碼中可以使用#pragma setlocale("..."),但功能很有限,比如Windows沒有utf8的locale,所以...)。
另外,和GCC對(duì)應(yīng)的wide-exec-charset呢?
寬執(zhí)行字符集如何解決? | 不妨先考慮一下 |
這才兩個(gè)編譯器,看起來就這么復(fù)雜了。而C++編譯器的數(shù)目遠(yuǎn)大于2.
要想跨平臺(tái),必須確保這兩個(gè)字符集都是“確定”的,而能勝任該任務(wù)的字符集,似乎理想的也只能是...
如果我們將源碼保存成utf8,執(zhí)行字符集也選為utf8,那么天下將太平了。使用非ASCII字符的源碼文件也就可以在不同國家的用戶間無障礙流通了 ;-).
源碼保存成UTF-8沒有什么困難,但是,執(zhí)行字符集需要是UTF-8。沒那么簡單
對(duì)GCC來說,這個(gè)問題很簡單(默認(rèn)的編碼選項(xiàng)足夠了):
只要源碼文件保存成utf8即可(帶或不帶BOM均可)
早期的gcc不接收帶BOM的utf8源碼文件,現(xiàn)在,至少在GCC4.6中,這一限制不再存在。
對(duì)MSVC來說,這個(gè)問題異常復(fù)雜:
對(duì)MSVC2003來說,只要源碼保存成不帶BOM的utf8即可
對(duì)MSVC2005、(沒在SP1基礎(chǔ)上裝熱補(bǔ)丁的)MSVC2008來說。完全沒辦法
直到MSVC2010sp1,才算提供了一個(gè)解決方案。源碼保存成帶BOM的utf8,utf16,...,然后添加
#pragma execution_character_set("utf-8")
要想跨GCC4.6+和MSVC2010sp1+,我們需要取它們的交集:也就是
源碼保存成帶BOM的utf8
為MSVC添加#pragma
//main.cpp#if _MSC_VER >= 1600#pragma execution_character_set("utf-8")#endifint main(){ char mystr[] = "老老實(shí)實(shí)的學(xué)問,來不得半點(diǎn)馬虎"; return sizeof mystr;}
等到MSVC支持C++11的String Literals之時(shí),我們就沒必要用那個(gè)蹩腳的pragma了,直接
char mystr[] = u8"老老實(shí)實(shí)的學(xué)問,來不得半點(diǎn)馬虎";
即可(盡管現(xiàn)在在GCC下沒問題,但要跨平臺(tái),估計(jì)要等到Visual C++ 12了)。
C++98中不是有個(gè)wchar_t么,它不是用來表示unicode字符的么?
Unicode 4.0標(biāo)準(zhǔn)的5.2節(jié)是如何說的:
The width of wchar_t is compiler-specific and can be as small as 8 bits. Consequently, programs that need to be portable across any C or C++ compilershould not use wchar_t for storing Unicode text. The wchar_t type is intended forstoring compiler-defined wide characters, which may be Unicode characters in some compilers.
在回頭看看GCC的選項(xiàng)
-fwide-exec-charset=charset
盡管GCC為其提供的默認(rèn)編碼是UTF16或UTF32(取決于wchar_t的寬度),但該編碼是可以隨意設(shè)置的。
盡管這個(gè)東西不保證跨平臺(tái),也很不好玩, 但是,由于在windows下面wchar_t用來表示utf16字符,而且直接對(duì)應(yīng)系統(tǒng)API接口,所以在類型char16_t普及之前,還是很重要的。
前面提到的u8就是C++11為“執(zhí)行字符集”所做的努力之一。
新明確規(guī)定了utf8、utf16和utf32這3種執(zhí)行字符集。
char* | u8"中文" |
char16_t* | u"中文" |
char32_t* | U"中文" |
可是C++11并沒有規(guī)定源碼字符集
const char* mystr=u8"中文";
C++標(biāo)準(zhǔn)對(duì)編譯器說,我不管這個(gè)文件的具體編碼是什么,但你必須給我生成對(duì)應(yīng)utf8編碼的字節(jié)流。
編譯器似乎有點(diǎn)傻了吧?不知道源文件的編碼,我如何轉(zhuǎn)換
于是:
MSVC說:源碼文件必須有BOM,不然我就認(rèn)為你是本地locale的編碼
GCC說:我認(rèn)為你就是utf8編碼,除非通過命令行通知我其他編碼
在C++11標(biāo)準(zhǔn)下,對(duì)源碼編碼 簡單的處理辦法還是,使用帶BOM的UTF8保存。
第二篇
今天,隨著Change QString's default codec to be UTF-8 進(jìn)入Qt5的master分支,我們總算可以重新審視一下Qt的中文支持問題。
20120516更新:建議閱讀QtCore模塊維護(hù)者Thiago Macieira 的文章 Source code must be UTF-8 and QString wants it
Qt5假定的執(zhí)行字符集是UTF8,不再允許用戶擅自改動(dòng)。這樣一來,Qt4中setCodecXXX的各種副作用不再存在,而且中文問題更為簡單。
QString s1 = "漢語";QString s2("漢語");QString s3 = tr("中文")QString s4 = QStringLiteral("中文");//只要字符串不需要翻譯,請(qǐng)關(guān)注這個(gè)QString s5 = QString::fromWCharArray(L"中文");QString s6 = u8"中文";//C++11QString s7 = tr(u8"中文")...
所有這些在Qt5默認(rèn)都會(huì)正常工作,唯一要求就是:確保你的C++的執(zhí)行字符集(the execution character set)是UTF-8
最簡單直接的用法,當(dāng)屬:
QString s1 = "漢語";QString s2("漢語");QString s6 = u8"中文";//C++11...
這有什么問題呢?
定義宏QT_NO_CAST_FROM_ASCII之后,上述代碼無法將通過編譯(對(duì)了,這個(gè)宏似乎應(yīng)該改個(gè)名字才對(duì),叫QT_NO_CAST_FROM_CSTRING會(huì)名副其實(shí)一些)
在Qt4中,QObject::tr()是被濫用(誤用)的函數(shù)之一:
QString s3 = tr("中文")...
原因:
在Qt4,不少用戶被鋪天蓋地的setCodecForTr()所影響,進(jìn)而靠它來解決中文問題。
它的用途是用來進(jìn)行翻譯(I18N和L10N)的,如果你沒有這方面的需求,真的沒必要用它。(在Qt4中,我只注意到有2個(gè)大陸網(wǎng)友和1個(gè)日本網(wǎng)友有需求并真正進(jìn)行過這方面的嘗試,那么其他應(yīng)該算誤用吧?)
剛開始接觸Qt和QString時(shí),曾多次想過,為什么不用wchar_t,為什么,...
QString s5 = QString::fromWCharArray(L"中文");
這個(gè)東西在Windows下真的很有用:首先它是Windows系統(tǒng)API所用字符串,其次它和QString內(nèi)部表示相同。但是由于MSVC處于種種考慮,鼓勵(lì)大家使用TEXT/_T,反倒使大家對(duì)它比較陌生。
但是從C++標(biāo)準(zhǔn)來說,wchar_t畢竟不是char16_t,所以跨平臺(tái)性不好。在linux下,這行代碼需要utf32到utf16的轉(zhuǎn)換。
這是一個(gè)宏,一個(gè)蠻復(fù)雜的宏:
QString s4 = QStringLiteral("中文");
在介紹這個(gè)宏之前,我們先看看下面寫法有什么劣勢(shì):
QString s1 = "漢語";QString s2("漢語");QString s3 = tr("中文")QString s6 = u8"中文";//C++11...
首先,2個(gè)漢字的字符串以UTF-8編碼的形式被編譯器放到了常量區(qū)。(至少占7個(gè)字節(jié)吧?)
然后,程序運(yùn)行時(shí),構(gòu)造QString實(shí)例,需要在堆上申請(qǐng)空間,存放utf16格式的相應(yīng)字符串。
有沒有存在浪費(fèi)?
QString 內(nèi)部是UTF16,如果C++編譯器在編譯期直接提供了UTF16的字符串,那么我們?cè)赒String內(nèi)部直接保存也就夠了。這樣
省掉存在兩份不同的拷貝(即相應(yīng)的轉(zhuǎn)換,malloc的成本)
對(duì)漢字來說,UTF16本身就是UTF8省空間
目前,我們還沒有可靠的方式在C++使用UTF16的執(zhí)行字符集(the execution character set)。
盡管 L"..."(wchar_t*) 在Windows下是UTF16,但是不具備跨平臺(tái)性。
C++11可以保證這一點(diǎn),u"..."(char16_t),但主流編譯器尚未提供完美支持。
這兩點(diǎn),導(dǎo)致了QStringLiteral的復(fù)雜性
源碼見 qtbase/src/corelib/tools/qstring.h
(代碼中使用宏、模板、lambda表達(dá)式,還是相當(dāng)復(fù)雜的,此處只摘片段)
如果編譯器支持char16_t,則直接使用
#define QT_UNICODE_LITERAL_II(str) u"" strtypedef char16_t qunicodechar;...
否則。如果在Windows平臺(tái)下,或者在其他的wchar_t寬度為2的環(huán)境下,使用wchar_t
#if defined(Q_CC_MSVC)# define QT_UNICODE_LITERAL_II(str) L##str#else# define QT_UNICODE_LITERAL_II(str) L"" str#endiftypedef wchar_t qunicodechar;...
否則。編譯器不支持,Qt作為一個(gè)庫,肯定也沒有辦法
# define QStringLiteral(str) QString::fromUtf8(str, sizeof(str) - 1)
本文標(biāo)題:QString亂談(2)&QT5中文亂碼問題
文章來源:http://www.rwnh.cn/article24/gcgece.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、做網(wǎng)站、電子商務(wù)、網(wǎng)站收錄、、建站公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)