• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            只要你和計(jì)算機(jī)打交道,這些問(wèn)題可以說(shuō)是天天會(huì)遇到,但是很多人是似懂非懂, 能真正完全理解的人卻不多, 下面是個(gè)人的一些理解,有錯(cuò)歡迎指正.

            最早的計(jì)算機(jī)只支持ASCII碼, 具體來(lái)說(shuō)就是用1個(gè)字節(jié)(最高位為0, 沒(méi)有用)表示0到127,總共128個(gè)字符, 這樣就可以完全滿(mǎn)足英語(yǔ)應(yīng)用的要求了。

            后來(lái)擴(kuò)展到歐洲語(yǔ)系,理論上一個(gè)字節(jié)可以表示256個(gè)字符, 歐洲人就把剩余的128個(gè)字符(最高位為1)按照自己語(yǔ)言(法語(yǔ),德語(yǔ)...)的要求擴(kuò)充應(yīng)用了起來(lái), 好像也能滿(mǎn)足需要。

            然后又到了亞洲國(guó)家,比如中國(guó),中文漢字有十多萬(wàn),這剩余的128個(gè)字符根本不夠我用啊, 怎么辦? 于是就有了兩個(gè)字節(jié)的編碼,如中文的GBK, GB2312, BIG5等,當(dāng)然日語(yǔ),韓語(yǔ)等其他亞洲國(guó)家也有自己編碼方式。

            這就是所謂的多字節(jié)編碼(MBCS)方式, Win95/98時(shí)代只支持這種方式, 那時(shí)候處理字符串非常痛苦, 因?yàn)樗锩嬗行┳址且粋€(gè)字節(jié)表示的,也有一些是多個(gè)字節(jié)表示的, 比如字符串"你好abc", 里面明明是5個(gè)字符,strlen返回長(zhǎng)度卻是7, 你要正確識(shí)別字符個(gè)數(shù),可以使用類(lèi)似_mbslen的API, 但是實(shí)際上該API內(nèi)部會(huì)綁定當(dāng)前的字符集, 不然神仙也識(shí)別不了。

            要統(tǒng)一解決上面的問(wèn)題, 需要有一個(gè)世界通用的統(tǒng)一編碼格式, 那就是UNICODE。
             UNICODE個(gè)人感覺(jué)分廣義和狹義, 廣義的UNICODE包括UTF8, UCS2, UCS4, 而狹義的UNICODE(主要是Windows平臺(tái))就是指UCS2。
            先說(shuō)UCS2, Windows平臺(tái)上常說(shuō)的UNICODE實(shí)際上就是指UCS2, 簡(jiǎn)單來(lái)說(shuō)就是統(tǒng)一用2個(gè)字節(jié)的編碼,表示實(shí)際上所有語(yǔ)言的常用字符。
            再說(shuō)UTF8, 有了上面的UCS2,為甚么還有要UTF8? UCS2把任何字符全都編碼成2個(gè)字節(jié)(包括我們常用的英文字符), 這樣極大地增加了網(wǎng)絡(luò)傳輸和數(shù)據(jù)存儲(chǔ)的開(kāi)銷(xiāo),于是就有了UTF8。UTF8對(duì)英文字符還是1個(gè)字節(jié)存儲(chǔ),只對(duì)其他語(yǔ)言字符用多個(gè)字節(jié)存儲(chǔ)(2-6個(gè)字節(jié))。UTF8和UNICODE可以完全對(duì)應(yīng)的相互轉(zhuǎn)換, 具體可以參考這里
            為什么還要有 UCS4? UCS2用2個(gè)字節(jié),最多也只能表示0xFFFF+1 = 65536個(gè)字符, 但是我們僅漢字就有十多萬(wàn),所以UCS2/UTF8收錄的也只是我們一些常用的漢字, 所以我們需要UCS4, 用4個(gè)字節(jié)表示一個(gè)字符,可以表示0xFFFFFFFF+1=4294967296個(gè)字符, 它才是我們以后的終極解決方案。

            在Windows上不同編碼方式的相互轉(zhuǎn)換可以通過(guò)WideCharToMultiByteMutiByteToWideChar進(jìn)行, 它里面WideChar就是指UCS2, 可以看到它這里把UTF8也命名成MultiByte, 是不是有點(diǎn)誤導(dǎo)...

            下面再談小大小端(little-endian, big-endian).

            計(jì)算機(jī)是以字節(jié)為尋址單位的,這就涉及到字(2個(gè)字節(jié)), 雙字(4個(gè)字節(jié))及其他多字節(jié)單位 在計(jì)算機(jī)內(nèi)如何排布的問(wèn)題, 這里無(wú)非就是2種:低字節(jié)在低地址的little-endian和高字節(jié)在低地址的big-endian.
            如何區(qū)分當(dāng)前系統(tǒng)是哪種類(lèi)型的大小端? 曾經(jīng)看到有經(jīng)驗(yàn)的程序員也以當(dāng)前的操作系統(tǒng)類(lèi)型來(lái)判斷, 實(shí)際上系統(tǒng)的大小端和你的CPU架構(gòu)體系相關(guān)聯(lián), 比如說(shuō)X86是小端, PowPC是大端,ARM則是可控制(默認(rèn)也是小端)。
            要判斷當(dāng)前環(huán)境是大小端實(shí)際上很簡(jiǎn)單: bool IsLittleEndian()  {  int i=1;  return (*(char *)&i == 1); }
            曾經(jīng)看到公司跨平臺(tái)的代碼沒(méi)有通過(guò)大小端轉(zhuǎn)換,直接通過(guò)memcpy某個(gè)表示長(zhǎng)度的int在客戶(hù)端之間傳送,卻沒(méi)有發(fā)生問(wèn)題, 感覺(jué)很奇怪, 最后發(fā)現(xiàn)原來(lái)公司的所有native客戶(hù)端(Win, Mac, ios, Android,BlackBerry,Linux)全都是小端。感覺(jué)現(xiàn)在大端的應(yīng)用主要是網(wǎng)絡(luò)字節(jié)序, Java內(nèi)部全都是大端。
            上面的UCS2和UCS4因?yàn)槎际怯枚嘧止?jié)表示一個(gè)字符, 所以實(shí)際上都有大小端的問(wèn)題,比如分別對(duì)應(yīng)UCS2-LE和UCS2-BE,Windows上的UNICODE實(shí)際上是UCS2-LE, UTF8因?yàn)槭亲止?jié)流,所以沒(méi)有大小端的問(wèn)題。

            下面再說(shuō)一下BOM (Byte Order Mark), 上面說(shuō)了各種編碼方式以及大小端的問(wèn)題, 那么我們?cè)趺粗滥硞€(gè)文本或者數(shù)據(jù)流是何種編碼方式? 
            一般來(lái)說(shuō)有3種方法:一種是分本顯示指定, 比如web里html頭一般會(huì)有這么一段"content="text/html;charset=utf-8"; 要不就是大家默認(rèn)約定,比如自定義的網(wǎng)絡(luò)數(shù)據(jù)流內(nèi)的字符串一般都會(huì)用UTF8編碼; 還有一種就是用BOM,通過(guò)在文件頭里填入BOM規(guī)定的字節(jié),從而區(qū)分文件是何種編碼類(lèi)型: 
            UTF-8 0xEF 0xBB 0xBF
            UCS2 BE 0xFE 0xFF
            UCS2 LE 0xFF 0xFE
            UCS4 BE 0x00 0x00 0xFE 0xFF
            UCS4 LE 0xFF 0xFE 0x00 0x00
            有興趣的同學(xué)可以用notepad保存,試下各種效果, 然后用UltraEdit的16進(jìn)制方式查看驗(yàn)證。

            上面關(guān)于各種字符編碼方式的集合構(gòu)成了所謂的字符集/代碼頁(yè)相關(guān)的概念, 下面是是一些常用的代碼頁(yè)及其字符集: 
            代碼頁(yè)(CodePage)字符集(CharSet)
            Description
            936
            GB2312
            簡(jiǎn)體中文(GB2312)
            950
            BIG5
            繁體中文(BIG5)
            1200
            UTF-16
            Unicode (UCS2-LE)
            1201
            unicodeFFFE
            Unicode (UCS2-BE)
            65000
            UTF-7
            Unicode (UTF-7)
            65001
            UTF-8
            Unicode (UTF-8)
            65005
            UTF-32
            Unicode (UCS4-LE)
            65006
            UTF-32 (BE)
            Unicode (UCS4-BE)

            最后討論下C++編程中常見(jiàn)的關(guān)于字符編碼方式相關(guān)的問(wèn)題。

            在C++編程中, 我們常打交道的無(wú)非是編輯器和編譯器, 對(duì)編輯器起來(lái)說(shuō),我們常遇到就是亂碼問(wèn)題, 比如中文注釋顯示或是保存不了等, 解決辦法就是把你的文件保存成Unicode(UTF8)。
            對(duì)于編譯器來(lái)說(shuō), 編碼方式取決于它對(duì)C++標(biāo)準(zhǔn)的支持程度, 比如C++ 11以前,字符串我們只能指定成2種:一種是MBCS,如char* p="abc哈哈"; 還有一種是UCS2, 比如wchar_t*p = L"abc哈哈", 這樣編譯器就知道你要表示的字符串類(lèi)型。C++11之后,標(biāo)準(zhǔn)增加了UTF8和UCS4的支持, 比如char* p=u8"abc哈哈"表示UTF8,wchar_t* p=u"abc哈哈"表示UCS2(實(shí)際上和L"xxxx"一樣), char32_t* p=U"abc哈哈"表示UCS4。這里要區(qū)分編譯期和運(yùn)行期, 盡管C++11之前在編譯期我們沒(méi)法告訴編譯器我們這個(gè)常量串是UTF8格式的,但是程序運(yùn)行期我們還是可以使用所有的編碼式(MBCS/UTF8/UCS2/UCS4), 因?yàn)檫@些最終在內(nèi)存里都是二進(jìn)制流。
            另外C++11還增加了UTF8, UCS2, UCS4相互轉(zhuǎn)碼的支持:
            std::codecvt_utf8 封裝了UTF8相關(guān)的編碼轉(zhuǎn)換
            std::codecvt_utf16 封裝了UCS2相關(guān)的編碼轉(zhuǎn)換
            std::codecvt_utf8_utf16 封裝了UTF8與UCS2的編碼轉(zhuǎn)換

            對(duì)于C++跨平臺(tái)開(kāi)發(fā), 我們經(jīng)常遇到的就是默認(rèn)用那種編碼方式的問(wèn)題,我們會(huì)發(fā)現(xiàn)Windows 的UCS2解決方案對(duì)其他平臺(tái)來(lái)說(shuō)是個(gè)異類(lèi), 一般來(lái)說(shuō)有2種解決方法:
            一種是統(tǒng)一用UTF8 , 但是這樣對(duì)Windows來(lái)說(shuō)有點(diǎn)麻煩, 因?yàn)閃indows的API都是UCS2的,所以這種方式意味著任何字符串在傳給Windows API 之前都要從UTF8轉(zhuǎn)成UCS2; 還有一種就是用#define宏了, Windows上將字符串相關(guān)宏全都定義成UCS2, 其他平臺(tái)則全都定義成UTF8, 該方式要求就你在寫(xiě)代碼時(shí)頭腦要比較清醒,因?yàn)橥瑯拥拇a在不同平臺(tái)上的編碼格式是不一樣的。

            一直很好奇,誰(shuí)知道Windows為什么不用UTF8,非要搞得和其他平臺(tái)不一樣?
            posted on 2015-07-25 01:11 Richard Wei 閱讀(4694) 評(píng)論(2)  編輯 收藏 引用 所屬分類(lèi): C++

            FeedBack:
            # re: 關(guān)于字符集,編碼格式,大小端的簡(jiǎn)單總結(jié)
            2015-07-25 01:40 | test
            因?yàn)閚t內(nèi)核用的是ucs2,那是89年,utf8到了92年才發(fā)明出來(lái)。  回復(fù)  更多評(píng)論
              
            # re: 關(guān)于字符集,編碼格式,大小端的簡(jiǎn)單總結(jié)
            2015-07-25 19:55 | Richard Wei
            @test
            看來(lái)確實(shí)是歷史原因, 不過(guò)對(duì)于運(yùn)行期的程序來(lái)說(shuō),個(gè)人倒是更贊同Windows的做法,忽略?xún)?nèi)存因素,Windows的UCS2編碼相對(duì)于其他平臺(tái)的UTF8更統(tǒng)一和高效。  回復(fù)  更多評(píng)論
              
            久久国产精品无码一区二区三区| 性色欲网站人妻丰满中文久久不卡| 国产精品一区二区久久精品| 人妻无码久久一区二区三区免费| 久久久久久久亚洲Av无码| 久久超乳爆乳中文字幕| 久久99国产精品成人欧美| 久久SE精品一区二区| 99久久精品无码一区二区毛片| 午夜视频久久久久一区| 久久精品国产亚洲77777| 国产真实乱对白精彩久久| 7777精品久久久大香线蕉| 成人精品一区二区久久| 久久久久亚洲av综合波多野结衣| 久久99精品国产麻豆宅宅| 久久精品卫校国产小美女| 国产免费福利体检区久久| 久久久久久久久久久久中文字幕| 久久免费香蕉视频| 国产精品青草久久久久婷婷| 日韩人妻无码一区二区三区久久99| 国内精品久久久久久99蜜桃| 久久人与动人物a级毛片| 久久中文精品无码中文字幕| 伊人久久免费视频| 久久国产一区二区| 久久99国产精品尤物| 色天使久久综合网天天| 久久久久人妻精品一区三寸蜜桃 | 精品国产乱码久久久久久浪潮| 亚洲AV日韩AV永久无码久久| 偷偷做久久久久网站| 97精品伊人久久大香线蕉| 伊人久久五月天| 欧美精品九九99久久在观看| 亚洲国产天堂久久久久久| 色婷婷久久综合中文久久一本| 久久精品国产亚洲Aⅴ蜜臀色欲| 天天综合久久久网| 亚洲成色999久久网站|