青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 319, comments - 22, trackbacks - 0, articles - 11
  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

15款很棒的 JavaScript 開發(fā)工具

ugmbbc發(fā)布于 2011-05-17 14:18:36|3743 次閱讀 字體: 打印預(yù)覽 分享至新浪微博 轉(zhuǎn)貼到開心網(wǎng) 分享到校內(nèi)人人網(wǎng) 添加到Google書簽

網(wǎng)絡(luò)軟件

感謝山邊小溪的投遞
在開發(fā)中,借助得力的工具可以事半功倍。今天,這篇文章向大家分享最新收集的15款非常有用的 JavaScript 開發(fā)工具。
TestSwarm: Continious & Distributed JS Testing

TestSwarm是Mozilla實(shí)驗(yàn)室推出的一個(gè)開源項(xiàng)目,它旨在為開發(fā)者提供在多個(gè)瀏覽器版本上快速輕松測(cè)試自己JavaScript代碼的方法。
Javascript-212 in Useful JavaScript and jQuery Tools, Libraries, Plugins

Minimee
在網(wǎng)絡(luò)上,速度是很重要的,Minimee能幫助你將CSS和JavaScript文件進(jìn)行自動(dòng)壓縮和打包。
Javascript-169 in Useful JavaScript and jQuery Tools, Libraries, Plugins

Doctor JS
Doctor JS 是一款幫你分析 JavaScript 代碼的工具,測(cè)試你的代碼在多態(tài)、原型、異常和回調(diào)方面寫得怎么樣。
Javascript-174 in Useful JavaScript and jQuery Tools, Libraries, Plugins

Remy Sharp’s JSConsole
一個(gè)在線的 JavaScript 控制臺(tái)工具,對(duì)于測(cè)試、調(diào)試和演示非常有用。
Javascript-269 in Useful JavaScript and jQuery Tools, Libraries, Plugins

JavaScript Library Boilerplate
JavaScript Library Boilerplate 幫助你隨時(shí)隨地創(chuàng)建自己的 JavaScript 庫。
Javascript-260 in Useful JavaScript and jQuery Tools, Libraries, Plugins

jsdoc-toolkit
JsDoc Toolkit 是一款輔助工具,你只需要根據(jù)約定在 JavaScript 代碼中添加相應(yīng)的注釋,它就可以根據(jù)這些注釋來自動(dòng)生成API文檔。
Js-010 in Useful JavaScript and jQuery Tools, Libraries, Plugins

Jasmine: BDD for your JavaScript
Jasmine 是一個(gè)有名的javascript單元測(cè)試框架,它是獨(dú)立的“行為驅(qū)動(dòng)開發(fā)”框架。
Js-011 in Useful JavaScript and jQuery Tools, Libraries, Plugins

ObfuscateJS: JavaScript compressor
一款 JavaScript 混淆工具,去除空白和注釋,重命名變量等。
Javascript-282 in Useful JavaScript and jQuery Tools, Libraries, Plugins

PEG.js
PEG.js 是一個(gè)JavaScript的表達(dá)式語法解析器,它使您能夠輕松地建立復(fù)雜的數(shù)據(jù)或計(jì)算機(jī)程序語言的快速分析器。
Javascript-228 in Useful JavaScript and jQuery Tools, Libraries, Plugins

JSONView
JSONView 是一款幫助你在瀏覽器中查看JSON文檔的Firefox插件。
Js-014 in Useful JavaScript and jQuery Tools, Libraries, Plugins

JSonduit
JSonduit 是一個(gè)將網(wǎng)頁內(nèi)容轉(zhuǎn)換為 JSON 格式訂閱器的工具。
Javascript-182 in Useful JavaScript and jQuery Tools, Libraries, Plugins

jsplumb
jsPlumb 為開發(fā)者提供了可視化鏈接元素到頁面的方法,可以結(jié)合jQuery、MooTools 和 YUI3使用。
Javascript-193 in Useful JavaScript and jQuery Tools, Libraries, Plugins

Helma
Helma 是一個(gè)用來開發(fā)快速、穩(wěn)定的Web應(yīng)用程序的開源框架,它使用JavaScript 來作為服務(wù)端腳本環(huán)境,從而可以省略編譯周期。
Js-015 in Useful JavaScript and jQuery Tools, Libraries, Plugins

HTML + JSON Report
一款將 JSON 數(shù)據(jù)轉(zhuǎn)換為可讀性更高的HTML格式內(nèi)容的在線工具。
Javascript-300 in Useful JavaScript and jQuery Tools, Libraries, Plugins

JSON Editor
這個(gè)編輯器可以幫助你方便的編輯 JSON 字符串。
Javascript-222 in Useful JavaScript and jQuery Tools, Libraries, Plugins
你可能還喜歡

  • 推薦40個(gè)優(yōu)秀的免費(fèi)CSS工具
  • 分享18個(gè)常用的網(wǎng)站性能測(cè)試工具
  • 推薦25個(gè)提高網(wǎng)站可用性和轉(zhuǎn)化率的工具
  • JavaScript初學(xué)者應(yīng)注意的七個(gè)細(xì)節(jié)
  • 你可能不知道的10個(gè)JavaScript小技巧

  • (編譯來源:夢(mèng)想天空  原文來自:Useful JavaScript and jQuery Tools, Libraries, Plugins

     

    posted @ 2011-05-17 18:59 RTY 閱讀(339) | 評(píng)論 (0)編輯 收藏

    VirtualBox 宣布了 4.0.8 版本,該版本改進(jìn)了對(duì) Gnome 3 的 3D 支持。同時(shí)還修復(fù)了不少bug,包括改變 guest 窗體大小時(shí)可能導(dǎo)致程序崩潰的問題以及 Ubuntu 11.04 以及 Fedora 15 下 Gnome 3 的渲染問題。

    VirtualBox 是一款功能強(qiáng)大的 x86 虛擬機(jī)軟件,它不僅具有豐富的特色,而且性能也很優(yōu)異。

    更多關(guān)于VirtualBox的詳細(xì)信息,或者下載地址請(qǐng)點(diǎn)這里

    posted @ 2011-05-17 18:55 RTY 閱讀(401) | 評(píng)論 (0)編輯 收藏

    20+ Useful jQuery Content Slider Scripts and Tutorials

    Posted by: Adrian, In: Coding, Tutorials, On: May 16, 2011 | 2 Comments

    Maybe you’ve seen some businesses with beautifully designed websites that also have a slider which displays their available products and services; and since then you’ve been asking yourself how it’s done? If you still haven’t found out, then lend me an ear, because here’s the answer. It’s done with jQuery.

    So what is jQuery? As you probably know, there’s JavaScript – a scripting language, but Query is just a branch. jQuery is used to make easier the effects and interaction with the development code and works just like JavaScript. Released in January 2006, it gains popularity pretty quickly as it’s a nice technology that helps making the websites over the internet more interactive and fun. Also it takes less code than with JavaScript to create effects like drop down menus, animations, drag and drop elements and form validation.

    So, as it is easy and simple to use, needs less coding and creates interesting and beautiful effects, why not try making a slider with your recent products to put on your website? Here are 20+ of the most useful jQuery content slider scripts and tutorials. Hope to have inspired at least some of you and soon we will see more sites that are interactive and client oriented, saving space and showcasing their offer into nicely designed sliders.

    Rotating Image Slider with jQuery

    Parallax Slider with jQuery

    Compact News Previewer with jQuery

    Awkward Showcase – A jQuery Plugin

    WOW Slider

    Automatic Image Slider w/ CSS & jQuery

    Making a Mosaic Slideshow With jQuery & CSS

    How to Make Auto-Advancing Slideshows

    Coding a Rotating Image Slideshow w/ CSS3 and jQuery

    Create Beautiful jQuery slider tutorial

    CU3ER Image Slider

    jQueryGlobe – jQuery Plugin

    Nivo Slider

    Piecemaker XML Gallery

    Slide Deck

    Slides

    Slider Gallery with jQuery

    Estro – jQuery Ken Burns & swipe effect slider

    FSS – Full Screen Sliding Website Plugin

    li JQuery Slider/Image Rotator

    Point of ViUU

    posted @ 2011-05-17 18:52 RTY 閱讀(660) | 評(píng)論 (0)編輯 收藏

    IntelliJ IDEA 10.5 正式版發(fā)布了,建議所有人升級(jí)。IDEA 10.5 是一個(gè)重要的升級(jí)版本,該版本主要的改進(jìn)包括:

    • 完全支持 Java 7

      Java 7 migration helpers

    • 重構(gòu)功能、搜索替換功能界面的重構(gòu),簡(jiǎn)化代碼自動(dòng)完成

      In-place search-replace


      In-place introduce refactorings

    • 支持 Chrome 的 JavaScript 調(diào)試器
    • 支持 Groovy 1.8 和 Spring 3.1

      Shift-less code completion

      Spring 3.1 profiles

       

    • JavaScript, Android and Flex 開發(fā)改進(jìn)
    • Jetty 集成
    • XSLT2 支持

    完整內(nèi)容請(qǐng)看官方發(fā)行說明:http://www.jetbrains.com/idea/whatsnew/

    posted @ 2011-05-17 18:50 RTY 閱讀(656) | 評(píng)論 (0)編輯 收藏

    安裝Msysgit

    下一步

    同意GNU協(xié)議

    選擇安裝位置,下一步

    選擇TrueType  Front,下一步

    不創(chuàng)建啟動(dòng)文件夾

    默認(rèn)Git Bash,就可以了

    選擇使用OpenSSH

    選擇默認(rèn)的Checkout Style

    安裝完成了

    配置本地的Git

    就這樣安裝好Msysgit后,就可以開始配置開發(fā)環(huán)境了,在你的工作目錄建立一個(gè)新的文件夾Git,比如我的

    選擇Git文件夾,右鍵,選擇Git Bash Here,會(huì)彈出shell命令行界面

    生成你的Public Key

    輸入命令

    ssh-keygen –C “你的email地址 “ –t rsa

    就會(huì)為你生成一個(gè) SSH Key,然后會(huì)詢問一些保存文件的位置,設(shè)置密碼神馬的,直接回車,回車,回車,默認(rèn)的就可以了

    因?yàn)橹饕窃诒镜厥褂茫刹皇褂每诹睿苯踊剀嚲涂梢粤耍?/p>

    好了,現(xiàn)在為你生成了sshkey了。

    設(shè)置Github帳號(hào)的Public Key

    如果你有一個(gè)github的賬號(hào)的話,

    登陸github.Com 網(wǎng)站,在SSH Public Keys 設(shè)置你的SSH Public Keys

    創(chuàng)建一個(gè)數(shù)據(jù)倉庫

    設(shè)置相關(guān)的信息

    設(shè)置你的Email和Nickname

    現(xiàn)在回到你的工作目錄,可以選擇設(shè)置你默認(rèn)的email和nickname
    輸入命令

    git config –global user.email 你的email地址
    git config –global user.name "Arthur"

    Clone你的項(xiàng)目

    右鍵你的工作目錄Git,選擇Git GUI,選擇克隆已有版本庫

    輸入你在github的項(xiàng)目地址,例如

    git@github.com:caijiamx/Magento-Theme.git

    會(huì)彈出一個(gè)框出來讓你是否選擇信任github,輸入yes

    然后就會(huì)從github拉取數(shù)據(jù)了,

    前面簡(jiǎn)單的介紹如何克隆版本庫,現(xiàn)在就要正式的開始工作了。

    命令行下的Git開發(fā)

    新建一個(gè)工作文件夾,右鍵打開 Git Bash,輸入

    ssh git@github.com

    選擇yes,加入到hosts中

    信任git@github.com站點(diǎn)

    配置你的Github上Username和Token

    設(shè)置你的github 用戶名

    git config –global github.user caijiamx

    設(shè)置你的git賬戶的token

    Git config –global github.token your token

    這個(gè)token在github,com的Account Settings->Account Admin右側(cè)找到。

    我們重新開始上面介紹的從GUI拉取數(shù)據(jù),現(xiàn)在我們從命令開始你的項(xiàng)目

    Git下的開發(fā)

    為你的項(xiàng)目添加說明文件

    touch readme.txt
    //輸入hello world

    將新建的文件添加到暫存區(qū),輸入命令

    git add readme.txt

    提交你的更改 輸入命令

    git commit –m "first commit"

    添加遠(yuǎn)程服務(wù)器倉庫,輸入命令

    git remote add origin git@github.com:directoo/Magento-Theme.git

    提交你的更改到服務(wù)器,輸入命令

    git push origin master

    參考資源

    github set up git

    如何設(shè)置你的SSH Key

    github官方幫助教程

    初次運(yùn)行 Git 前的配置

    posted @ 2011-05-15 00:30 RTY 閱讀(866) | 評(píng)論 (0)編輯 收藏

    1、Run-Time Library

    Run-Time Library是編譯器提供的標(biāo)準(zhǔn)庫,提供一些基本的庫函數(shù)和系統(tǒng)調(diào)用。
    我們一般使用的Run-Time Library是C Run-Time Libraries。當(dāng)然也有Standard C++ libraries。 
    C Run-Time Libraries實(shí)現(xiàn)ANSI C的標(biāo)準(zhǔn)庫。VC安裝目錄的CRT目錄有C Run-Time庫的大部分源代碼。

    C Run-Time Libraries有靜態(tài)庫版本,也有動(dòng)態(tài)鏈接庫版本;有單線程版本,也有多線程版本;還有調(diào)試和非調(diào)試版本。
    可以在"project"-"settings"-"C/C++"-"Code Generation"中選擇Run-Time Library的版本。

    動(dòng)態(tài)鏈接庫版本:
    /MD Multithreaded DLL 使用導(dǎo)入庫MSVCRT.LIB
    /MDd Debug Multithreaded DLL 使用導(dǎo)入庫MSVCRTD.LIB

    靜態(tài)庫版本:
    /ML Single-Threaded 使用靜態(tài)庫LIBC.LIB 
    /MLd Debug Single-Threaded 使用靜態(tài)庫LIBCD.LIB
    /MT Multithreaded 使用靜態(tài)庫LIBCMT.LIB
    /MTd Debug Multithreaded 使用靜態(tài)庫LIBCMTD.LIB

    C Run-Time Library的標(biāo)準(zhǔn)io部分與操作系統(tǒng)的關(guān)系很密切,在Windows上,CRT的io部分代碼只是一個(gè)包裝,底層要用到操作系統(tǒng)內(nèi)核kernel32.dll中的函數(shù),在編譯時(shí)使用導(dǎo)入庫kernel32.lib。這也就是為什么在嵌入式環(huán)境中,我們一般不能直接使用C標(biāo)準(zhǔn)庫。
    在Linux環(huán)境當(dāng)然也有C標(biāo)準(zhǔn)庫,例如:
    ld -o output /lib/crt0.o hello.o -lc
    參數(shù)"-lc"就是在引用C標(biāo)準(zhǔn)庫libc.a。猜一猜"-lm"引用哪個(gè)庫文件?

    2、常見的編譯參數(shù)

    VC建立項(xiàng)目時(shí)總會(huì)定義"Win32"。控制臺(tái)程序會(huì)定義"_CONSOLE",否則會(huì)定義"_WINDOWS"。Debug版定義"_DEBUG",Release版定義"NDEBUG"

     

    與MFC DLL有關(guān)的編譯常數(shù)包括:
    _WINDLL 表示要做一個(gè)用到MFC的DLL
    _USRDLL 表示做一個(gè)用戶DLL(相對(duì)MFC擴(kuò)展DLL而言) 
    _AFXDLL 表示使用MFC動(dòng)態(tài)鏈接庫
    _AFXEXT 表示要做一個(gè)MFC擴(kuò)展DLL
    所以:
    Regular, statically linked to MFC _WINDLL,_USRDLL 
    Regular, using the shared MFC DLL _WINDLL,_USRDLL,_AFXDLL
    Extension DLL _WINDLL,_AFXDLL,_AFXEXT

    CL.EXE編譯所有源文件,LINK.EXE鏈接EXE和DLL,LIB.EXE產(chǎn)生靜態(tài)庫。

    3、subsystem和可執(zhí)行文件的啟動(dòng)

    LINK的時(shí)候需要指定/subsystem,這個(gè)鏈接選項(xiàng)告訴Windows如何運(yùn)行可執(zhí)行文件。
    控制臺(tái)程序是/subsystem:"console"
    其它程序一般都是/subsystem:"windows "

     

    將 subsystem 選成"console"后,Windows在進(jìn)入可執(zhí)行文件的代碼前(如mainCRTStartup),就會(huì)產(chǎn)生一個(gè)控制臺(tái)窗口。
    如果選擇"windows",操作系統(tǒng)就不產(chǎn)生console窗口,該類型應(yīng)用程序的窗口由用戶自己創(chuàng)建。

    可執(zhí)行文件都有一個(gè)Entry Point,LINK時(shí)可以用/entry指定。缺省情況下,如果subsystem是“console”,Entry Point是 mainCRTStartup(ANSI)或wmainCRTStartuup(UNICODE),即:
    /subsystem:"console" /entry:"mainCRTStartup" (ANSI)
    /subsystem:"console" /entry:"wmainCRTStartuup" (UNICODE)
    mainCRTStartup 或 wmainCRTStartuup 會(huì)調(diào)用main或wmain。
    值得一提的是,在進(jìn)入應(yīng)用程序的Entry Point前,Windows的裝載器已經(jīng)做過C變量的初始化,有初值的全局變量擁有了它們的初值,沒有初值的變量被設(shè)為0。

    如果subsystem是“windows”,Entry Point是WinMain(ANSI)或wWinMain(UINCODE),即:
    /subsystem:"windows" /entry:"WinMainCRTStartup" (ANSI)
    /sbusystem:"windows" /entry:"wWinMainCRTStartup" (UINCODE)
    WinMainCRTStartup 或 wWinMainCRTStartup 會(huì)調(diào)用 WinMain 或 wWinMain。

    這些入口點(diǎn)函數(shù),在CRT目錄都可以看到源代碼,例如(為了簡(jiǎn)潔,我刪除了原代碼的一些條件編譯):

    void mainCRTStartup(void)
    {
            int mainret;
    
            /* Get the full Win32 version */
            _osver = GetVersion();
            _winminor = (_osver >> 8) & 0x00FF ;
            _winmajor = _osver & 0x00FF ;
            _winver = (_winmajor << 8) + _winminor;
            _osver = (_osver >> 16) & 0x00FFFF ;
    
    #ifdef _MT
            if ( !_heap_init(1) )               /* initialize heap */
    #else  /* _MT */
            if ( !_heap_init(0) )               /* initialize heap */
    #endif  /* _MT */
                fast_error_exit(_RT_HEAPINIT);  /* write message and die */
    
    #ifdef _MT
            if( !_mtinit() )                    /* initialize multi-thread */
                fast_error_exit(_RT_THREAD);    /* write message and die */
    #endif  /* _MT */
    
            __try {
                _ioinit();                      /* initialize lowio */
                _acmdln = (char *)GetCommandLineA();        /* get cmd line info */
                _aenvptr = (char *)__crtGetEnvironmentStringsA();        /* get environ info */
                _setargv();
                _setenvp();
                __initenv = _environ;
                mainret = main(__argc, __argv, _environ);
                exit(mainret);
            }
            __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
            {
                _exit( GetExceptionCode() );        /* Should never reach here */
            } /* end of try - except */
    }  

    如果使用MFC框架,WinMain也會(huì)被埋藏在MFC庫中(APPMODUL.CPP):
    extern "C" int WINAPI
    _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine, int nCmdShow)
    {
    // call shared/exported WinMain
    return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
    }
    對(duì)于ANSI版本,"_tWinMain"就是"WinMain";對(duì)于UINCODE版本,"_tWinMain"就是"wWinMain"。可參見afx.h:

    #ifdef _UNICODE
    #define _tmain wmain
    #define _tWinMain wWinMain
    #else
    #define _tmain main
    #define _tWinMain WinMain
    #endif

    全局C++對(duì)象的構(gòu)造函數(shù)是在什么地方調(diào)用的?答案是在進(jìn)入應(yīng)用程序的Entry Point后,在調(diào)用main函數(shù)前的初始化操作中。所以MFC的theApp的構(gòu)造函數(shù)是在_tWinMain之前調(diào)用的。

    4、不顯示Console窗口的Console程序

    在默認(rèn)情況下/subsystem 和/entry開關(guān)是匹配的,也就是:
    "console"對(duì)應(yīng)"mainCRTStartup"或者"wmainCRTStartup"
    "windows"對(duì)應(yīng)"WinMain"或者"wWinMain"
    我們可以通過手動(dòng)修改的方法使他們不匹配。例如:

     

    #include "windows.h"
    #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 設(shè)置入口地址 
    void main(void)
    {
    MessageBox(NULL, "hello", "Notice", MB_OK);
    }

    這個(gè)Console程序就不會(huì)顯示Console窗口。如果選/MLd的話,這個(gè)程序只需要鏈接LIBCD.LIB user32.lib kernel32.lib。

    其實(shí)如果不想看到Console窗口,還有一個(gè)更直接的方法:那就是直接在EXE文件中將PE文件頭的Subsystem從3改成2。在EXE文件中,PE文件頭的偏移地址是0x3c,Subsystem是一個(gè)WORD,它在PE文件頭中的偏移是0x5c。

    5、MFC的庫文件

    MFC的庫可以靜態(tài)鏈接,也可以動(dòng)態(tài)鏈接。靜態(tài)庫和動(dòng)態(tài)庫又有Debug和Release,ANSI和Unicode版本之分。

     

    靜態(tài)MFC庫主要有:
    ANSI Debug NAFXCWD.LIB
    ANSI Release NAFXCW.LIB
    Unicode Debug UAFXCWD.LIB
    Unicode Release UAFXCW.LIB 

    動(dòng)態(tài)鏈接庫主要有;
    ANSI Debug MFCxxD.LIB (core,MFCxxD.DLL), 
    MFCOxxD.LIB (OLE,MFCOxxD.DLL), 
    MFCDxxD.LIB (database,MFCDxxD.DLL), 
    MFCNxxD.LIB (network,MFCNxxD.DLL), 
    MFCSxxD.LIB (static)

    ANSI Release MFCxx.LIB (combined,MFCxx.DLL)
    MFCSxx.LIB (static)

    Unicode Debug MFCxxUD.LIB (core,MFCxxUD.DLL), 
    MFCOxxUD.LIB (OLE,MFCOxxUD.DLL), 
    MFCDxxUD.LIB (database,MFCDxxUD.DLL), 
    MFCNxxUD.LIB (network,MFCNxxUD.DLL), 
    MFCSxxUD.LIB (static)

    Unicode Release MFCxxU.DLL (combined,MFCxxU.DLL), 
    MFCSxxU.LIB (static)

    上面的LIB文件除了MFCSxx(D、U、UD).LIB以外都是導(dǎo)入庫。
    MFC動(dòng)態(tài)鏈接庫版本也需要靜態(tài)鏈接一些文件,這些文件就放在MFCSxx(D、U、UD).LIB中。例如包含_tWinMain的appmodul.cpp。

    6、結(jié)束語

    研究這些問題的動(dòng)機(jī)是想弄清楚我們的程序是如何裝載、運(yùn)行的。但是,由于Windows不是開源平臺(tái),我也只能研究到PE文件(Windows上可執(zhí)行文件的格式)。entry point、subsystem都是PE文件頭的一部分。

    Windows在進(jìn)入PE文件的entry point之前做了些什么,就看不到了,只能大概推測(cè):應(yīng)該是創(chuàng)建一個(gè)進(jìn)程,裝載PE文件和所有需要的DLL,初始化C變量,然后從某個(gè)起點(diǎn)函數(shù)開始運(yùn)行。不同的subsystem,應(yīng)該有不同的起點(diǎn)。調(diào)用這個(gè)起點(diǎn)函數(shù)時(shí)應(yīng)該傳入PE文件的entry point地址。

     

    posted @ 2011-05-12 22:06 RTY 閱讀(539) | 評(píng)論 (0)編輯 收藏

    1 什么是堆棧

    編譯器一般使用堆棧實(shí)現(xiàn)函數(shù)調(diào)用。堆棧是存儲(chǔ)器的一個(gè)區(qū)域,嵌入式環(huán)境有時(shí)需要程序員自己定義一個(gè)數(shù)組作為堆棧。Windows為每個(gè)線程自動(dòng)維護(hù)一個(gè)堆棧,堆棧的大小可以設(shè)置。編譯器使用堆棧來堆放每個(gè)函數(shù)的參數(shù)、局部變量等信息。

    函數(shù)調(diào)用經(jīng)常是嵌套的,在同一時(shí)刻,堆棧中會(huì)有多個(gè)函數(shù)的信息,每個(gè)函數(shù)占用一個(gè)連續(xù)的區(qū)域。一個(gè)函數(shù)占用的區(qū)域被稱作幀(frame)。

    編譯器從高地址開始使用堆棧。 假設(shè)我們定義一個(gè)數(shù)組a[1024]作為堆棧空間,一開始棧頂指針指向a[1023]。如果棧里有兩個(gè)函數(shù)a和b,且a調(diào)用了b,棧頂指針會(huì)指向函數(shù)b的幀。如果函數(shù)b返回。棧頂指針就指向函數(shù)a的幀。如果在棧里放了太多東西造成溢出,破壞的是a[0]上面的東西。

    在多線程(任務(wù))環(huán)境,CPU的堆棧指針指向的存儲(chǔ)器區(qū)域就是當(dāng)前使用的堆棧。切換線程的一個(gè)重要工作,就是將堆棧指針設(shè)為當(dāng)前線程的堆棧棧頂?shù)刂贰?/p>

    不同CPU,不同編譯器的堆棧布局、函數(shù)調(diào)用方法都可能不同,但堆棧的基本概念是一樣的。

    2 函數(shù)調(diào)用約定

    函數(shù)調(diào)用約定包括傳遞參數(shù)的順序,誰負(fù)責(zé)清理參數(shù)占用的堆棧等,例如 :

     參數(shù)傳遞順序誰負(fù)責(zé)清理參數(shù)占用的堆棧
    __pascal從左到右調(diào)用者
    __stdcall從右到左被調(diào)函數(shù)
    __cdecl從右到左調(diào)用者

    調(diào)用函數(shù)的代碼和被調(diào)函數(shù)必須采用相同的函數(shù)的調(diào)用約定,程序才能正常運(yùn)行。在Windows上,__cdecl是C/C++程序的缺省函數(shù)調(diào)用約定。

    在有的cpu上,編譯器會(huì)用寄存器傳遞參數(shù),函數(shù)使用的堆棧由被調(diào)函數(shù)分配和釋放。這種調(diào)用約定在行為上和__cdecl有一個(gè)共同點(diǎn):實(shí)參和形參數(shù)目不符不會(huì)導(dǎo)致堆棧錯(cuò)誤。

    不過,即使用寄存器傳遞參數(shù),編譯器在進(jìn)入函數(shù)時(shí),還是會(huì)將寄存器里的參數(shù)存入堆棧指定位置。參數(shù)和局部變量一樣應(yīng)該在堆棧中有一席之地。參數(shù)可以被理解為由調(diào)用函數(shù)指定初值的局部變量。

    3 例子:__cdecl和__stdcall

    不同的CPU,不同的編譯器,堆棧的布局可能是不同的。本文以x86,VC++的編譯器為例。

    VC++編譯器的已經(jīng)不再支持__pascal, __fortran, __syscall等函數(shù)調(diào)用約定。目前只支持__cdecl和__stdcall。

    采用__cdecl或__stdcall調(diào)用方式的程序,在剛進(jìn)入子函數(shù)時(shí),堆棧內(nèi)容是一樣的。esp指向的棧頂是返回地址。這是被call指令壓入堆棧的。下面是參數(shù),左邊參數(shù)在上,右邊參數(shù)在下(先入棧)。

    如前表所示,__cdecl和__stdcall的區(qū)別是:__cdecl是調(diào)用者清理參數(shù)占用的堆棧,__stdcall是被調(diào)函數(shù)清理參數(shù)占用的堆棧。

    由于__stdcall的被調(diào)函數(shù)在編譯時(shí)就必須知道傳入?yún)?shù)的準(zhǔn)確數(shù)目(被調(diào)函數(shù)要清理堆棧),所以不能支持變參數(shù)函數(shù),例如printf。而且如果調(diào)用者使用了不正確的參數(shù)數(shù)目,會(huì)導(dǎo)致堆棧錯(cuò)誤。

    通過查看匯編代碼,__cdecl函數(shù)調(diào)用在call語句后會(huì)有一個(gè)堆棧調(diào)整語句,例如:

      a = 0x1234;
      b = 0x5678;
      c = add(a, b);

    對(duì)應(yīng)x86匯編:

      mov dword ptr [ebp-4],1234h
      mov dword ptr [ebp-8],5678h
      mov eax,dword ptr [ebp-8]
      push eax
      mov ecx,dword ptr [ebp-4]
      push ecx
      call 0040100a
      add esp,8
      mov dword ptr [ebp-0Ch],eax


    __stdcall的函數(shù)調(diào)用則不需要調(diào)整堆棧:

      call 00401005
      mov dword ptr [ebp-0Ch],eax

    函數(shù)

      int __cdecl add(int a, int b)
      {
      return a+b;
      }

    產(chǎn)生以下匯編代碼(Debug版本):

      push ebp
      mov ebp,esp
      sub esp,40h
      push ebx
      push esi
      push edi
      lea edi,[ebp-40h]
      mov ecx,10h
      mov eax,0CCCCCCCCh
      rep stos dword ptr [edi]
      mov eax,dword ptr [ebp+8]
      add eax,dword ptr [ebp+0Ch]
      pop edi
      pop esi
      pop ebx
      mov esp,ebp
      pop ebp
      ret // 跳轉(zhuǎn)到esp所指地址,并將esp+4,使esp指向進(jìn)入函數(shù)時(shí)的第一個(gè)參數(shù)

    再查看__stdcall函數(shù)的實(shí)現(xiàn),會(huì)發(fā)現(xiàn)與__cdecl函數(shù)只有最后一行不同:

      ret 8 // 執(zhí)行ret并清理參數(shù)占用的堆棧

    對(duì)于調(diào)試版本,VC++編譯器在“直接調(diào)用地址”時(shí)會(huì)增加檢查esp的代碼,例如:

      ta = (TAdd)add; // TAdd定義:typedef int (__cdecl *TAdd)(int a, int b);
      c = ta(a, b);

    產(chǎn)生以下匯編代碼:

      mov [ebp-10h],0040100a
      mov esi,esp
      mov ecx,dword ptr [ebp-8]
      push ecx
      mov edx,dword ptr [ebp-4]
      push edx
      call dword ptr [ebp-10h]
      add esp,8
      cmp esi,esp
      call __chkesp (004011e0)
      mov dword ptr [ebp-0Ch],eax

    __chkesp 代碼如下。如果esp不等于函數(shù)調(diào)用前保存的值,就會(huì)轉(zhuǎn)到錯(cuò)誤處理代碼。

      004011E0 jne __chkesp+3 (004011e3)
      004011E2 ret
      004011E3 ;錯(cuò)誤處理代碼

    __chkesp的錯(cuò)誤處理會(huì)彈出對(duì)話框,報(bào)告函數(shù)調(diào)用造成esp值不正確。 Release版本的匯編代碼要簡(jiǎn)潔得多。也不會(huì)增加 __chkesp。如果發(fā)生esp錯(cuò)誤,程序會(huì)繼續(xù)運(yùn)行,直到“遇到問題需要關(guān)閉”。

    3 補(bǔ)充說明

    函數(shù)調(diào)用約定只是“調(diào)用函數(shù)的代碼”和被調(diào)用函數(shù)之間的關(guān)系。

    假設(shè)函數(shù)A是__stdcall,函數(shù)B調(diào)用函數(shù)A。你必須通過函數(shù)聲明告訴編譯器,函數(shù)A是__stdcall。編譯器自然會(huì)產(chǎn)生正確的調(diào)用代碼。

    如果函數(shù)A是__stdcall。但在引用函數(shù)A的地方,你卻告訴編譯器,函數(shù)A是__cdecl方式,編譯器產(chǎn)生__cdecl方式的代碼,與函數(shù)A的調(diào)用約定不一致,就會(huì)發(fā)生錯(cuò)誤。

    以delphi調(diào)用VC函數(shù)為例,delphi的函數(shù)缺省采用__pascal約定,VC的函數(shù)缺省采用__cdecl約定。我們一般將VC的函數(shù)設(shè)為__stdcall,例如:

      int __stdcall add(int a, int b);

    在delphi中將這個(gè)函數(shù)也聲明為__stdcall,就可以調(diào)用了:

      function add(a: Integer; b: Integer): Integer;
      stdcall; external 'a.dll';

    因?yàn)榭紤]到可能被其它語言的程序調(diào)用,不少API采用__stdcall的調(diào)用約定。

    posted @ 2011-05-12 22:00 RTY 閱讀(480) | 評(píng)論 (0)編輯 收藏

    3 字符編碼模型

    程序員經(jīng)常會(huì)面對(duì)復(fù)雜的問題,而降低復(fù)雜性的最簡(jiǎn)單的方法就是分而治之。Peter Constable在他的文章"Character set encoding basics Understanding character set encodings and legacy encodings"中描述了字符編碼的四層模型。我覺得這種說法確實(shí)可以更清晰地展現(xiàn)字符編碼中發(fā)生的事情,所以在這里也介紹一下。

    3.1 字符的范圍(Abstract character repertoire)

    設(shè)計(jì)字符編碼的第一層就是確定字符的范圍,即要支持哪些字符。有些編碼方案的字符范圍是固定的,例如ASCII、ISO 8859 系列。有些編碼方案的字符范圍是開放的,例如Unicode的字符范圍就是世界上所有的字符。

    3.2 用數(shù)字表示字符(Coded character set)

    設(shè)計(jì)字符編碼的第二層是將字符和數(shù)字對(duì)應(yīng)起來。可以將這個(gè)層次理解成數(shù)學(xué)家(即從數(shù)學(xué)角度)看到的字符編碼。數(shù)學(xué)家看到的字符編碼是一個(gè)正整數(shù)。例如在Unicode中:漢字“字”對(duì)應(yīng)的數(shù)字是23383。漢字“”對(duì)應(yīng)的數(shù)字是134192。

    在寫html文件時(shí),可以通過輸入"字"來插入字符“字”。不過在設(shè)計(jì)字符編碼時(shí),我們還是習(xí)慣用16進(jìn)制表示數(shù)字。即將23383寫成0x5BD7,將134192寫成0x20C30。

    3.3 用基本數(shù)據(jù)類型表示字符(Character encoding form)

    設(shè)計(jì)字符編碼的第三層是用編程語言中的基本數(shù)據(jù)類型來表示字符。可以將這個(gè)層次理解成程序員看到的字符編碼。在Unicode中,我們有很多方式將數(shù)字23383表示成程序中的數(shù)據(jù),包括:UTF-8、UTF-16、UTF-32。UTF是“UCS Transformation Format”的縮寫,可以翻譯成Unicode字符集轉(zhuǎn)換格式,即怎樣將Unicode定義的數(shù)字轉(zhuǎn)換成程序數(shù)據(jù)。例如,“漢字”對(duì)應(yīng)的數(shù)字是0x6c49和0x5b57,而編碼的程序數(shù)據(jù)是:

     

    	BYTE data_utf8[] = {0xE6, 0xB1, 0x89, 0xE5, 0xAD, 0x97};	// UTF-8編碼
    	WORD data_utf16[] = {0x6c49, 0x5b57};				// UTF-16編碼
    	DWORD data_utf32[] = {0x6c49, 0x5b57};				// UTF-32編碼

     

    這里用BYTE、WORD、DWORD分別表示無符號(hào)8位整數(shù),無符號(hào)16位整數(shù)和無符號(hào)32位整數(shù)。UTF-8、UTF-16、UTF-32分別以BYTE、WORD、DWORD作為編碼單位。

    “漢字”的UTF-8編碼需要6個(gè)字節(jié)。“漢字”的UTF-16編碼需要兩個(gè)WORD,大小是4個(gè)字節(jié)。“漢字”的UTF-32編碼需要兩個(gè)DWORD,大小是8個(gè)字節(jié)。4.2節(jié)會(huì)介紹將數(shù)字映射到UTF編碼的規(guī)則。

    3.4 作為字節(jié)流的字符(Character encoding scheme)

    字符編碼的第四層是計(jì)算機(jī)看到的字符,即在文件或內(nèi)存中的字節(jié)流。例如,“字”的UTF-32編碼是0x5b57,如果用little endian表示,字節(jié)流是“57 5b 00 00”。如果用big endian表示,字節(jié)流是“00 00 5b 57”。

    字符編碼的第三層規(guī)定了一個(gè)字符由哪些編碼單位按什么順序表示。字符編碼的第四層在第三層的基礎(chǔ)上又考慮了編碼單位內(nèi)部的字節(jié)序。UTF-8的編碼單位是字節(jié),不受字節(jié)序的影響。UTF-16、UTF-32根據(jù)字節(jié)序的不同,又衍生出UTF-16LE、UTF-16BE、UTF-32LE、UTF-32BE四種編碼方案。LE和BE分別是Little Endian和Big Endian的縮寫。

    3.5 小結(jié)

    通過四層模型,我們又把字符編碼中發(fā)生的這些事情梳理了一遍。其實(shí)大多數(shù)代碼頁都不需要完整的四層模型,例如GB18030以字節(jié)為編碼單位,直接規(guī)定了字節(jié)序列和字符的映射關(guān)系,跳過了第二層,也不需要第四層。

    4 再談Unicode

    Unicode是國際組織制定的可以容納世界上所有文字和符號(hào)的字符編碼方案。Unicode用數(shù)字0-0x10FFFF來映射這些字符,最多可以容納1114112個(gè)字符,或者說有1114112個(gè)碼位。碼位就是可以分配給字符的數(shù)字。UTF-8、UTF-16、UTF-32都是將數(shù)字轉(zhuǎn)換到程序數(shù)據(jù)的編碼方案。

    Unicode字符集可以簡(jiǎn)寫為UCS(Unicode Character Set)。早期的Unicode標(biāo)準(zhǔn)有UCS-2、UCS-4的說法。UCS-2用兩個(gè)字節(jié)編碼,UCS-4用4個(gè)字節(jié)編碼。UCS-4根據(jù)最高位為0的最高字節(jié)分成2^7=128個(gè)group。每個(gè)group再根據(jù)次高字節(jié)分為256個(gè)平面(plane)。每個(gè)平面根據(jù)第3個(gè)字節(jié)分為256行 (row),每行有256個(gè)碼位(cell)。group 0的平面0被稱作BMP(Basic Multilingual Plane)。將UCS-4的BMP去掉前面的兩個(gè)零字節(jié)就得到了UCS-2。

    Unicode標(biāo)準(zhǔn)計(jì)劃使用group 0 的17個(gè)平面: 從BMP(平面0)到平面16,即數(shù)字0-0x10FFFF。《談?wù)刄nicode編碼》主要介紹了BMP的編碼,本文將介紹完整的Unicode編碼,并從多個(gè)角度瀏覽Unicode。本文的介紹基于Unicode 5.0.0版本。

    4.1 瀏覽Unicode

    先看一些數(shù)字:每個(gè)平面有2^16=65536個(gè)碼位。Unicode計(jì)劃使用了17個(gè)平面,一共有17*65536=1114112個(gè)碼位。其實(shí),現(xiàn)在已定義的碼位只有238605個(gè),分布在平面0、平面1、平面2、平面14、平面15、平面16。其中平面15和平面16上只是定義了兩個(gè)各占65534個(gè)碼位的專用區(qū)(Private Use Area),分別是0xF0000-0xFFFFD和0x100000-0x10FFFD。所謂專用區(qū),就是保留給大家放自定義字符的區(qū)域,可以簡(jiǎn)寫為PUA。

    平面0也有一個(gè)專用區(qū):0xE000-0xF8FF,有6400個(gè)碼位。平面0的0xD800-0xDFFF,共2048個(gè)碼位,是一個(gè)被稱作代理區(qū)(Surrogate)的特殊區(qū)域。它的用途將在4.2節(jié)介紹。

    238605-65534*2-6400-2408=99089。余下的99089個(gè)已定義碼位分布在平面0、平面1、平面2和平面14上,它們對(duì)應(yīng)著Unicode目前定義的99089個(gè)字符,其中包括71226個(gè)漢字。平面0、平面1、平面2和平面14上分別定義了52080、3419、43253和337個(gè)字符。平面2的43253個(gè)字符都是漢字。平面0上定義了27973個(gè)漢字。

    在更深入地了解Unicode字符前,我們先了解一下UCD。

    4.1.1 什么是UCD

    UCD是Unicode字符數(shù)據(jù)庫(Unicode Character Database)的縮寫。UCD由一些描述Unicode字符屬性和內(nèi)部關(guān)系的純文本或html文件組成。大家可以在Unicode組織的網(wǎng)站看到UCD的最新版本

    UCD中的文本文件大都是適合于程序分析的Unicode相關(guān)數(shù)據(jù)。其中的html文件解釋了數(shù)據(jù)庫的組織,數(shù)據(jù)的格式和含義。UCD中最龐大的文件無疑就是描述漢字屬性的文件Unihan.txt。在UCD 5.0,0中,Unihan.txt文件大小有28,221K字節(jié)。Unihan.txt中包含了很多有參考價(jià)值的索引,例如漢字部首、筆劃、拼音、使用頻度、四角號(hào)碼排序等。這些索引都是基于一些比較權(quán)威的辭典,但大多數(shù)索引只能檢索部分漢字。

    我介紹UCD的目的主要是為了使用其中的兩個(gè)概念:Block和Script。

    4.1.2 Block

    UCD中的Blocks.txt將Unicode的碼位分割成一些連續(xù)的Block,并描述了每個(gè)Block的用途:

    開始碼位結(jié)束碼位Block名稱(英文)Block名稱(中文)
    0000007FBasic Latin基本拉丁字母
    008000FFLatin-1 Supplement拉丁字母補(bǔ)充-1
    0100017FLatin Extended-A拉丁字母擴(kuò)充-A
    0180024FLatin Extended-B拉丁字母擴(kuò)充-B
    025002AFIPA Extensions國際音標(biāo)擴(kuò)充
    02B002FFSpacing Modifier Letters進(jìn)格修飾字符
    0300036FCombining Diacritical Marks組合附加符號(hào)
    037003FFGreek and Coptic希臘文和哥普特文
    040004FFCyrillic西里爾文
    0500052FCyrillic Supplement西里爾文補(bǔ)充
    0530058FArmenian亞美尼亞文
    059005FFHebrew希伯來文
    060006FFArabic基本阿拉伯文
    0700074FSyriac敘利亞文
    0750077FArabic Supplement阿拉伯文補(bǔ)充
    078007BFThaana塔納文
    07C007FFNKoN'Ko字母表
    0900097FDevanagari天成文書(梵文)
    098009FFBengali孟加拉文
    0A000A7FGurmukhi錫克教文
    0A800AFFGujarati古吉拉特文
    0B000B7FOriya奧里亞文
    0B800BFFTamil泰米爾文
    0C000C7FTelugu泰盧固文
    0C800CFFKannada卡納達(dá)文
    0D000D7FMalayalam德拉維族文
    0D800DFFSinhala僧伽羅文
    0E000E7FThai泰文
    0E800EFFLao老撾文
    0F000FFFTibetan藏文
    1000109FMyanmar緬甸文
    10A010FFGeorgian格魯吉亞文
    110011FFHangul Jamo朝鮮文
    1200137FEthiopic埃塞俄比亞文
    1380139FEthiopic Supplement埃塞俄比亞文補(bǔ)充
    13A013FFCherokee切羅基文
    1400167FUnified Canadian Aboriginal Syllabics加拿大印第安方言
    1680169FOgham歐甘文
    16A016FFRunic北歐古字
    1700171FTagalog塔加路文
    1720173FHanunoo哈努諾文
    1740175FBuhid布迪文
    1760177FTagbanwaTagbanwa文
    178017FFKhmer高棉文
    180018AFMongolian蒙古文
    1900194FLimbu林布文
    1950197FTai Le德宏傣文
    198019DFNew Tai Lue新傣文
    19E019FFKhmer Symbols高棉文
    1A001A1FBuginese布吉文
    1B001B7FBalinese巴厘文
    1D001D7FPhonetic Extensions拉丁字母音標(biāo)擴(kuò)充
    1D801DBFPhonetic Extensions Supplement拉丁字母音標(biāo)擴(kuò)充增補(bǔ)
    1DC01DFFCombining Diacritical Marks Supplement組合附加符號(hào)補(bǔ)充
    1E001EFFLatin Extended Additional拉丁字母擴(kuò)充附加
    1F001FFFGreek Extended希臘文擴(kuò)充
    2000206FGeneral Punctuation一般標(biāo)點(diǎn)符號(hào)
    2070209FSuperscripts and Subscripts上標(biāo)和下標(biāo)
    20A020CFCurrency Symbols貨幣符號(hào)
    20D020FFCombining Diacritical Marks for Symbols符號(hào)用組合附加符號(hào)
    2100214FLetterlike Symbols似字母符號(hào)
    2150218FNumber Forms數(shù)字形式
    219021FFArrows箭頭符號(hào)
    220022FFMathematical Operators數(shù)學(xué)運(yùn)算符號(hào)
    230023FFMiscellaneous Technical零雜技術(shù)用符號(hào)
    2400243FControl Pictures控制圖符
    2440245FOptical Character Recognition光學(xué)字符識(shí)別
    246024FFEnclosed Alphanumerics帶括號(hào)的字母數(shù)字
    2500257FBox Drawing制表符
    2580259FBlock Elements方塊元素
    25A025FFGeometric Shapes幾何形狀
    260026FFMiscellaneous Symbols零雜符號(hào)
    270027BFDingbats雜錦字型
    27C027EFMiscellaneous Mathematical Symbols-A零雜數(shù)學(xué)符號(hào)-A
    27F027FFSupplemental Arrows-A箭頭符號(hào)補(bǔ)充-A
    280028FFBraille Patterns盲文
    2900297FSupplemental Arrows-B箭頭符號(hào)補(bǔ)充-B
    298029FFMiscellaneous Mathematical Symbols-B零雜數(shù)學(xué)符號(hào)-B
    2A002AFFSupplemental Mathematical Operators數(shù)學(xué)運(yùn)算符號(hào)
    2B002BFFMiscellaneous Symbols and Arrows零雜符號(hào)和箭頭
    2C002C5FGlagolitic格拉哥里字母表
    2C602C7FLatin Extended-C拉丁字母擴(kuò)充-C
    2C802CFFCoptic科普特文
    2D002D2FGeorgian Supplement格魯吉亞文補(bǔ)充
    2D302D7FTifinagh提非納字母
    2D802DDFEthiopic Extended埃塞俄比亞文擴(kuò)充
    2E002E7FSupplemental Punctuation標(biāo)點(diǎn)符號(hào)補(bǔ)充
    2E802EFFCJK Radicals Supplement中日韓部首補(bǔ)充
    2F002FDFKangxi Radicals康熙字典部首
    2FF02FFFIdeographic Description Characters漢字結(jié)構(gòu)描述字符
    3000303FCJK Symbols and Punctuation中日韓符號(hào)和標(biāo)點(diǎn)
    3040309FHiragana平假名
    30A030FFKatakana片假名
    3100312FBopomofo注音符號(hào)
    3130318FHangul Compatibility Jamo朝鮮文兼容字母
    3190319FKanbun日文的漢字批注
    31A031BFBopomofo Extended注音符號(hào)擴(kuò)充
    31C031EFCJK Strokes中日韓筆劃
    31F031FFKatakana Phonetic Extensions片假名音標(biāo)擴(kuò)充
    320032FFEnclosed CJK Letters and Months帶括號(hào)的中日韓字母及月份
    330033FFCJK Compatibility中日韓兼容字符
    34004DBFCJK Unified Ideographs Extension A中日韓統(tǒng)一表意文字?jǐn)U充A
    4DC04DFFYijing Hexagram Symbols易經(jīng)六十四卦象
    4E009FFFCJK Unified Ideographs中日韓統(tǒng)一表意文字
    A000A48FYi Syllables彝文音節(jié)
    A490A4CFYi Radicals彝文字根
    A700A71FModifier Tone Letters聲調(diào)修飾字母
    A720A7FFLatin Extended-D拉丁字母擴(kuò)充-D
    A800A82FSyloti NagriSyloti Nagri字母表
    A840A87FPhags-paPhags-pa字母表
    AC00D7AFHangul Syllables朝鮮文音節(jié)
    D800DB7FHigh Surrogates高位替代
    DB80DBFFHigh Private Use Surrogates高位專用替代
    DC00DFFFLow Surrogates低位替代
    E000F8FFPrivate Use Area專用區(qū)
    F900FAFFCJK Compatibility Ideographs中日韓兼容表意文字
    FB00FB4FAlphabetic Presentation Forms字母變體顯現(xiàn)形式
    FB50FDFFArabic Presentation Forms-A阿拉伯文變體顯現(xiàn)形式-A
    FE00FE0FVariation Selectors字型變換選取器
    FE10FE1FVertical Forms豎排標(biāo)點(diǎn)符號(hào)
    FE20FE2FCombining Half Marks組合半角標(biāo)示
    FE30FE4FCJK Compatibility Forms中日韓兼容形式
    FE50FE6FSmall Form Variants小型變體形式
    FE70FEFFArabic Presentation Forms-B阿拉伯文變體顯現(xiàn)形式-B
    FF00FFEFHalfwidth and Fullwidth Forms半角及全角字符
    FFF0FFFFSpecials特殊區(qū)域
    100001007FLinear B Syllabary線形文字B音節(jié)文字
    10080100FFLinear B Ideograms線形文字B表意文字
    101001013FAegean Numbers愛琴海數(shù)字
    101401018FAncient Greek Numbers古希臘數(shù)字
    103001032FOld Italic古意大利文
    103301034FGothic哥特文
    103801039FUgaritic烏加里特楔形文字
    103A0103DFOld Persian古波斯文
    104001044FDeseret德塞雷特大學(xué)音標(biāo)
    104501047FShavian肅伯納速記符號(hào)
    10480104AFOsmanyaOsmanya字母表
    108001083FCypriot Syllabary塞浦路斯音節(jié)文字
    109001091FPhoenician腓尼基文
    10A0010A5FKharoshthi迦婁士悌文
    12000123FFCuneiform楔形文字
    124001247FCuneiform Numbers and Punctuation楔形文字?jǐn)?shù)字和標(biāo)點(diǎn)
    1D0001D0FFByzantine Musical Symbols東正教音樂符號(hào)
    1D1001D1FFMusical Symbols音樂符號(hào)
    1D2001D24FAncient Greek Musical Notation古希臘音樂符號(hào)
    1D3001D35FTai Xuan Jing Symbols太玄經(jīng)符號(hào)
    1D3601D37FCounting Rod Numerals算籌
    1D4001D7FFMathematical Alphanumeric Symbols數(shù)學(xué)用字母數(shù)字符號(hào)
    200002A6DFCJK Unified Ideographs Extension B中日韓統(tǒng)一表意文字?jǐn)U充 B
    2F8002FA1FCJK Compatibility Ideographs Supplement中日韓兼容表意文字補(bǔ)充
    E0000E007FTags標(biāo)簽
    E0100E01EFVariation Selectors Supplement字型變換選取器補(bǔ)充
    F0000FFFFFSupplementary Private Use Area-A補(bǔ)充專用區(qū)-A
    10000010FFFFSupplementary Private Use Area-B補(bǔ)充專用區(qū)-B

    Block是Unicode字符的一個(gè)屬性。屬于同一個(gè)Block的字符有著相近的用途。Block表中的開始碼位、結(jié)束碼位只是用來劃分出一塊區(qū)域,在開始碼位和結(jié)束碼位之間可能還有很多未定義的碼位。使用UniToy,大家可以按照Block瀏覽Unicode字符,既可以按列表顯示:

     

    也可以顯示每個(gè)字符的詳細(xì)信息:

    4.1.3 Script

    Unicode中每個(gè)字符都有一個(gè)Script屬性,這個(gè)屬性表明字符所屬的文字系統(tǒng)。Unicode目前支持以下Script:

    Script名稱(英文)Script名稱(中文)Script包含的字符數(shù)
    Arabic阿拉伯文966
    Armenian亞美尼亞文90
    Balinese巴厘文121
    Bengali孟加拉文91
    Bopomofo漢語注音符號(hào)64
    Braille盲文256
    Buginese布吉文30
    Buhid布迪文20
    Canadian Aboriginal加拿大印第安方言630
    Cherokee切羅基文85
    CommonCommon5020
    Coptic科普特文128
    Cuneiform楔形文字982
    Cypriot塞浦路斯音節(jié)文字55
    Cyrillic西里爾文277
    Deseret德塞雷特大學(xué)音標(biāo)80
    Devanagari天成文書(梵文)107
    Ethiopic埃塞俄比亞文461
    Georgian格魯吉亞文120
    Gothic哥特文94
    Glagolitic格拉哥里字母表27
    Greek希臘文506
    Gujarati古吉拉特文83
    Gurmukhi錫克教文77
    Han漢文71570
    Hangul韓文書寫系統(tǒng)11619
    Hanunoo哈努諾文21
    Hebrew希伯來文133
    Hiragana平假名89
    InheritedInherited461
    Kannada卡納達(dá)文86
    Katakana片假名164
    Kharoshthi迦婁士悌文65
    Khmer高棉文146
    Lao老撾文65
    Latin拉丁文系1070
    Limbu林布文(尼泊爾東部)66
    Linear B線形文字B211
    Malayalam德拉維族文(印度)78
    Mongolian蒙古文152
    Myanmar緬甸文78
    New Tai Lue新傣文80
    NkoN'Ko字母表59
    Ogham歐甘文字29
    Old Italic古意大利文35
    Old Persian古波斯文50
    Oriya奧里亞文81
    OsmanyaOsmanya字母表40
    Phags PaPhags Pa字母表(蒙古)56
    Phoenician腓尼基文27
    Runic古代北歐文78
    Shavian肅伯納速記符號(hào)48
    Sinhala僧伽羅文80
    Syloti NagriSyloti Nagri字母表(印度)44
    Syriac敘利亞文77
    Tagalog塔加路文(菲律賓)20
    TagbanwaTagbanwa文(菲律賓)18
    Tai Le德宏傣文35
    Tamil泰米爾文71
    Telugu泰盧固文(印度)80
    Thaana馬爾代夫書寫體50
    Thai泰國文86
    Tibetan藏文195
    Tifinagh提非納字母表55
    Ugaritic烏加里特楔形文字31
    Yi彝文1220

    其中,有兩個(gè)Script值有著特殊的含義:

    • Common:Script屬性為Common的字符可能在多個(gè)文字系統(tǒng)中使用,不是某個(gè)文字系統(tǒng)特有的。例如:空格、數(shù)字等。
    • Inherited:Script屬性為Inherited的字符會(huì)繼承前一個(gè)字符的Script屬性。主要是一些組合用符號(hào),例如:在“組合附加符號(hào)”區(qū)(0x300-0x36f),字符的Script屬性都是Inherited。

    UCD中的Script.txt列出了每個(gè)字符的Script屬性。使用UniToy可以按照Script屬性查看字符。例如:

    左側(cè)Script窗口中,第一層節(jié)點(diǎn)是按英文字母順序排列的Script屬性。第二層節(jié)點(diǎn)是包含該Script文字的行(row),點(diǎn)擊后顯示該行內(nèi)屬于這個(gè)Script的字符。這樣,就可以集中查看屬于同一文字系統(tǒng)的字符。

    4.1.4 Unicode中的漢字

    前面提過,在Unicode已定義的99089個(gè)字符中,有71226個(gè)字符是漢字。它們的分布如下:

    Block名稱開始碼位結(jié)束碼位數(shù)量
    中日韓統(tǒng)一表意文字?jǐn)U充A34004db56582
    中日韓統(tǒng)一表意文字4e009fbb20924
    中日韓兼容表意文字f900fa2d302
    中日韓兼容表意文字fa30fa6a59
    中日韓兼容表意文字fa70fad9106
    中日韓統(tǒng)一表意文字?jǐn)U充B200002a6d642711
    中日韓兼容表意文字補(bǔ)充2f8002fa1d542

    UCD的Unihan.txt中的部首偏旁索引(kRSUnicode)可以檢索全部71226個(gè)漢字。kRSUnicode的部首是按照康熙字典定義的,共214個(gè)部首。簡(jiǎn)體字按照簡(jiǎn)體部首對(duì)應(yīng)的繁體部首檢索。UniToy整理了康熙字典部首對(duì)應(yīng)的簡(jiǎn)體部首,提供了按照部首檢索漢字的功能:

    4.2 UTF編碼

    在字符編碼的四個(gè)層次中,第一層的范圍和第二層的編碼在4.1節(jié)已經(jīng)詳細(xì)討論過了。本節(jié)討論第三層的UTF編碼和第四層的字節(jié)序,主要談?wù)劦谌龑拥腢TF編碼,即怎樣將Unicode定義的編碼轉(zhuǎn)換成程序數(shù)據(jù)。

    4.2.1 UTF-8

    UTF-8以字節(jié)為單位對(duì)Unicode進(jìn)行編碼。從Unicode到UTF-8的編碼方式如下:

    Unicode編碼(16進(jìn)制)UTF-8 字節(jié)流(二進(jìn)制)
    000000 - 00007F0xxxxxxx
    000080 - 0007FF110xxxxx 10xxxxxx
    000800 - 00FFFF1110xxxx 10xxxxxx 10xxxxxx
    010000 - 10FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

    UTF-8的特點(diǎn)是對(duì)不同范圍的字符使用不同長(zhǎng)度的編碼。對(duì)于0x00-0x7F之間的字符,UTF-8編碼與ASCII編碼完全相同。UTF-8編碼的最大長(zhǎng)度是4個(gè)字節(jié)。從上表可以看出,4字節(jié)模板有21個(gè)x,即可以容納21位二進(jìn)制數(shù)字。Unicode的最大碼位0x10FFFF也只有21位。

    例1:“漢”字的Unicode編碼是0x6C49。0x6C49在0x0800-0xFFFF之間,使用用3字節(jié)模板了:1110xxxx 10xxxxxx 10xxxxxx。將0x6C49寫成二進(jìn)制是:0110 1100 0100 1001, 用這個(gè)比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。

    例2:“”字的Unicode編碼是0x20C30。0x20C30在0x010000-0x10FFFF之間,使用用4字節(jié)模板了:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。將0x20C30寫成21位二進(jìn)制數(shù)字(不足21位就在前面補(bǔ)0):0 0010 0000 1100 0011 0000,用這個(gè)比特流依次代替模板中的x,得到:11110000 10100000 10110000 10110000,即F0 A0 B0 B0。

    4.2.2 UTF-16

    UniToy有個(gè)“輸出編碼”功能,可以輸出當(dāng)前選擇的文本編碼。因?yàn)閁niToy內(nèi)部采用UTF-16編碼,所以輸出的編碼就是文本的UTF-16編碼。例如:如果我們輸出“漢”字的UTF-16編碼,可以看到0x6C49,這與“漢”字的Unicode編碼是一致的。如果我們輸出“”字的UTF-16編碼,可以看到0xD843, 0xDC30。“”字的Unicode編碼是0x20C30,它的UTF-16編碼是怎樣得到的呢?

    4.2.2.1 編碼規(guī)則

    UTF-16編碼以16位無符號(hào)整數(shù)為單位。我們把Unicode編碼記作U。編碼規(guī)則如下:

    • 如果U<0x10000,U的UTF-16編碼就是U對(duì)應(yīng)的16位無符號(hào)整數(shù)(為書寫簡(jiǎn)便,下文將16位無符號(hào)整數(shù)記作WORD)。
    • 如果U≥0x10000,我們先計(jì)算U'=U-0x10000,然后將U'寫成二進(jìn)制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16編碼(二進(jìn)制)就是:110110yyyyyyyyyy110111xxxxxxxxxx。

    為什么U'可以被寫成20個(gè)二進(jìn)制位?Unicode的最大碼位是0x10ffff,減去0x10000后,U'的最大值是0xfffff,所以肯定可以用20個(gè)二進(jìn)制位表示。例如:“”字的Unicode編碼是0x20C30,減去0x10000后,得到0x10C30,寫成二進(jìn)制是:0001 0000 1100 0011 0000。用前10位依次替代模板中的y,用后10位依次替代模板中的x,就得到:1101100001000011 1101110000110000,即0xD843 0xDC30。

    4.2.2.2 代理區(qū)(Surrogate)

    按照上述規(guī)則,Unicode編碼0x10000-0x10FFFF的UTF-16編碼有兩個(gè)WORD,第一個(gè)WORD的高6位是110110,第二個(gè)WORD的高6位是110111。可見,第一個(gè)WORD的取值范圍(二進(jìn)制)是11011000 00000000到11011011 11111111,即0xD800-0xDBFF。第二個(gè)WORD的取值范圍(二進(jìn)制)是11011100 00000000到11011111 11111111,即0xDC00-0xDFFF。

    為了將一個(gè)WORD的UTF-16編碼與兩個(gè)WORD的UTF-16編碼區(qū)分開來,Unicode編碼的設(shè)計(jì)者將0xD800-0xDFFF保留下來,并稱為代理區(qū)(Surrogate):

    D800DB7FHigh Surrogates高位替代
    DB80DBFFHigh Private Use Surrogates高位專用替代
    DC00DFFFLow Surrogates低位替代

    高位替代就是指這個(gè)范圍的碼位是兩個(gè)WORD的UTF-16編碼的第一個(gè)WORD。低位替代就是指這個(gè)范圍的碼位是兩個(gè)WORD的UTF-16編碼的第二個(gè)WORD。那么,高位專用替代是什么意思?我們來解答這個(gè)問題,順便看看怎么由UTF-16編碼推導(dǎo)Unicode編碼。

    解:如果一個(gè)字符的UTF-16編碼的第一個(gè)WORD在0xDB80到0xDBFF之間,那么它的Unicode編碼在什么范圍內(nèi)?我們知道第二個(gè)WORD的取值范圍是0xDC00-0xDFFF,所以這個(gè)字符的UTF-16編碼范圍應(yīng)該是0xDB80 0xDC00到0xDBFF 0xDFFF。我們將這個(gè)范圍寫成二進(jìn)制:

    1101101110000000 11011100 00000000 - 1101101111111111 1101111111111111

    按照編碼的相反步驟,取出高低WORD的后10位,并拼在一起,得到

    1110 0000 0000 0000 0000 - 1111 1111 1111 1111 1111

    即0xe0000-0xfffff,按照編碼的相反步驟再加上0x10000,得到0xf0000-0x10ffff。這就是UTF-16編碼的第一個(gè)WORD在0xdb80到0xdbff之間的Unicode編碼范圍,即平面15和平面16。因?yàn)閁nicode標(biāo)準(zhǔn)將平面15和平面16都作為專用區(qū),所以0xDB80到0xDBFF之間的保留碼位被稱作高位專用替代。

    4.2.3 UTF-32

    UTF-32編碼以32位無符號(hào)整數(shù)為單位。Unicode的UTF-32編碼就是其對(duì)應(yīng)的32位無符號(hào)整數(shù)。

    4.2.4 字節(jié)序

    根據(jù)字節(jié)序的不同,UTF-16可以被實(shí)現(xiàn)為UTF-16LE或UTF-16BE,UTF-32可以被實(shí)現(xiàn)為UTF-32LE或UTF-32BE。例如:

    字符Unicode編碼UTF-16LEUTF-16BEUTF32-LEUTF32-BE
    0x6C4949 6C6C 4949 6C 00 0000 00 6C 49
    0x20C3043 D8 30 DCD8 43 DC 3030 0C 02 0000 02 0C 30

     

    那么,怎么判斷字節(jié)流的字節(jié)序呢?

     

    Unicode標(biāo)準(zhǔn)建議用BOM(Byte Order Mark)來區(qū)分字節(jié)序,即在傳輸字節(jié)流前,先傳輸被作為BOM的字符"零寬無中斷空格"。這個(gè)字符的編碼是FEFF,而反過來的FFFE(UTF-16)和FFFE0000(UTF-32)在Unicode中都是未定義的碼位,不應(yīng)該出現(xiàn)在實(shí)際傳輸中。下表是各種UTF編碼的BOM:

    UTF編碼Byte Order Mark
    UTF-8EF BB BF
    UTF-16LEFF FE
    UTF-16BEFE FF
    UTF-32LEFF FE 00 00
    UTF-32BE00 00 FE FF

    5 結(jié)束語

    程序員的工作就是將復(fù)雜的世界簡(jiǎn)單地表達(dá)出來,希望這篇文章也能做到這一點(diǎn)。本文的初稿完成于2007年2月14日。我會(huì)在我的個(gè)人主頁http://www.fmddlmyy.cn維護(hù)這篇文章的最新版本。

    posted @ 2011-05-12 21:58 RTY 閱讀(531) | 評(píng)論 (0)編輯 收藏

    我曾經(jīng)寫過一篇《談?wù)刄nicode編碼,簡(jiǎn)要解釋UCS、UTF、BMP、BOM等名詞》(以下簡(jiǎn)稱《談?wù)刄nicode編碼》),在網(wǎng)上流傳較廣,我也收到不少朋友的反饋。本文探討《談?wù)刄nicode編碼》中未介紹或介紹較少的代碼頁、Surrogates等問題,補(bǔ)充一些Unicode資料,順帶介紹一下我最近編寫的一個(gè)Unicode工具:UniToy。本文雖然是前文的補(bǔ)充,但在寫作上盡量做到獨(dú)立成篇。

    標(biāo)題中的“淺談”是對(duì)自己的要求,我希望文字能盡量淺顯易懂。但本文還是假設(shè)讀者知道字節(jié)、16進(jìn)制,了解《談?wù)刄nicode編碼》中介紹過的字節(jié)序和Unicode的基本概念。

    0 UniToy

    UniToy是我編寫的一個(gè)小工具。通過UniToy,我們可以全方位、多角度地查看Unicode,了解Unicode和語言、代碼頁的關(guān)系,完成一些文字編碼的相關(guān)工作。本文的一些內(nèi)容是通過UniToy演示的。大家可以從我的網(wǎng)站(www.fmddlmyy.cn)下載UniToy的演示版本

    1 文字的顯示

    1.1 發(fā)生了什么?

    我們首先以Windows為例來看看文字顯示過程中發(fā)生了什么。用記事本打開一個(gè)文本文件,可以看到文件包含的文字:

    字符和編碼

    如果我們用UltraEdit或Hex Workshop查看這個(gè)文件的16進(jìn)制數(shù)據(jù),可以看到:

    D7D6 B7FB BACD B1E0 C2EB

    我們看到:文件“例子GBK.txt”有10個(gè)字節(jié),依次是“D7 D6 B7 FB BA CD B1 E0 C2 EB”,這就是記事本從文件中讀到的內(nèi)容。記事本是用來打開文本文件的,所以它會(huì)調(diào)用Windows的文本顯示函數(shù)將讀到的數(shù)據(jù)作為文本顯示。Windows首先將文本數(shù)據(jù)轉(zhuǎn)換到它內(nèi)部使用的編碼格式:Unicode,然后按照文本的Unicode去字體文件中查找字體圖像,最后將圖像顯示到窗口上。 總結(jié)一下前面的分析,文字的顯示應(yīng)該是這樣的:

    • 步驟1:文字首先以某種編碼保存在文件中。
    • 步驟2:Windows將文件中的文字編碼映射到Unicode。
    • 步驟3:Windows按照Unicode在字體文件中查找字體圖像,畫到窗口上。
    所謂編碼就是用數(shù)字表示字符,例如用D7D6表示“字”。當(dāng)然,編碼還意味著約定,即大家都認(rèn)可。從《談?wù)刄nicode編碼》中,我們知道Unicode也是一種文字編碼,它的特殊性在于它是由國際組織設(shè)計(jì),可以容納全世界所有語言文字。而我們平常使用的文字編碼通常是針對(duì)一個(gè)區(qū)域的語言、文字設(shè)計(jì),只支持特定的語言文字。例如:在上面的例子中,文件“例子GBK.txt”采用的就是GBK編碼。

     

    如果上述3個(gè)步驟中任何一步發(fā)生了錯(cuò)誤,文字就不能被正確顯示,例如:

    • 錯(cuò)誤1:如果弄錯(cuò)了編碼,例如將Big5編碼的文字當(dāng)作GBK編碼,就會(huì)出現(xiàn)亂碼。

    • 錯(cuò)誤2:如果從特定編碼到Unicode的映射發(fā)生錯(cuò)誤,例如文本數(shù)據(jù)中出現(xiàn)該編碼方案未定義的字符,Windows就會(huì)使用缺省字符,通常是?。

    • 如果當(dāng)前字體不支持要顯示的字符,Windows就會(huì)顯示字體文件中的缺省圖像:空白或方格。

    在Unicode被廣泛使用前,有多少種語言、文字,就可能有多少種文字編碼方案。一種文字也可能有多種編碼方案。那么我們?cè)趺创_定文本數(shù)據(jù)采用了什么編碼?

    1.2 采用了哪種編碼?

    按照慣例,文本文件中的數(shù)據(jù)都是文本編碼,那么它怎么表明自己的編碼格式?在記事本的“打開”對(duì)話框上:

    我們可以看到記事本支持4種編碼格式:ANSI、Unicode、Unicode big endian、UTF-8。如果讀者看過《談?wù)刄nicode編碼》,對(duì)Unicode、Unicode big endian、UTF-8應(yīng)該不會(huì)陌生,其實(shí)它們更準(zhǔn)確的名稱應(yīng)該是UTF-16LE(Little Endian)、UTF-16BE(Big Endian)和UTF-8,它們是基于Unicode的不同編碼方案。

    在《談?wù)刄nicode編碼》中介紹過,Windows通過在文本文件開頭增加一些特殊字節(jié)(BOM)來區(qū)分上述3種編碼,并將沒有BOM的文本數(shù)據(jù)按照ANSI代碼頁處理。那么什么是代碼頁,什么是ANSI代碼頁?

    2 代碼頁和字符集

    2.1 Windows的代碼頁

    2.1.1 代碼頁

    代碼頁(Code Page)是個(gè)古老的專業(yè)術(shù)語,據(jù)說是IBM公司首先使用的。代碼頁和字符集的含義基本相同,代碼頁規(guī)定了適用于特定地區(qū)的字符集合,和這些字符的編碼。可以將代碼頁理解為字符和字節(jié)數(shù)據(jù)的映射表。

    Windows為自己支持的代碼頁都編了一個(gè)號(hào)碼。例如代碼頁936就是簡(jiǎn)體中文 GBK,代碼頁950就是繁體中文 Big5。代碼頁的概念比較簡(jiǎn)單,就是一個(gè)字符編碼方案。但要說清楚Windows的ANSI代碼頁,就要從Windows的區(qū)域(Locale)說起了。

    2.1.2 區(qū)域和ANSI代碼頁

    微軟為了適應(yīng)世界上不同地區(qū)用戶的文化背景和生活習(xí)慣,在Windows中設(shè)計(jì)了區(qū)域(Locale)設(shè)置的功能。Local是指特定于某個(gè)國家或地區(qū)的一組設(shè)定,包括代碼頁,數(shù)字、貨幣、時(shí)間和日期的格式等。在Windows內(nèi)部,其實(shí)有兩個(gè)Locale設(shè)置:系統(tǒng)Locale和用戶Locale。系統(tǒng)Locale決定代碼頁,用戶Locale決定數(shù)字、貨幣、時(shí)間和日期的格式。我們可以在控制面板的“區(qū)域和語言選項(xiàng)”中設(shè)置系統(tǒng)Locale和用戶Locale:

    每個(gè)Locale都有一個(gè)對(duì)應(yīng)的代碼頁。Locale和代碼頁的對(duì)應(yīng)關(guān)系,大家可以參閱我的另一篇文章《談?wù)刉indows程序中的字符編碼》的附錄1。系統(tǒng)Locale對(duì)應(yīng)的代碼頁被作為Windows的默認(rèn)代碼頁。在沒有文本編碼信息時(shí),Windows按照默認(rèn)代碼頁的編碼方案解釋文本數(shù)據(jù)。這個(gè)默認(rèn)代碼頁通常被稱作ANSI代碼頁(ACP)。

    ANSI代碼頁還有一層意思,就是微軟自己定義的代碼頁。在歷史上,IBM的個(gè)人計(jì)算機(jī)和微軟公司的操作系統(tǒng)曾經(jīng)是PC的標(biāo)準(zhǔn)配置。微軟公司將IBM公司定義的代碼頁稱作OEM代碼頁,在IBM公司的代碼頁基礎(chǔ)上作了些增補(bǔ)后,作為自己的代碼頁,并冠以ANSI的字樣。我們?cè)?#8220;區(qū)域和語言選項(xiàng)”高級(jí)頁面的代碼頁轉(zhuǎn)換表中看到的包含ANSI字樣的代碼頁都是微軟自己定義的代碼頁。例如:

    • 874 (ANSI/OEM - 泰文)
    • 932 (ANSI/OEM - 日文 Shift-JIS)
    • 936 (ANSI/OEM - 簡(jiǎn)體中文 GBK)
    • 949 (ANSI/OEM - 韓文)
    • 950 (ANSI/OEM - 繁體中文 Big5)
    • 1250 (ANSI - 中歐)
    • 1251 (ANSI - 西里爾文)
    • 1252 (ANSI - 拉丁文 I)
    • 1253 (ANSI - 希臘文)
    • 1254 (ANSI - 土耳其文)
    • 1255 (ANSI - 希伯來文)
    • 1256 (ANSI - 阿拉伯文)
    • 1257 (ANSI - 波羅的海文)
    • 1258 (ANSI/OEM - 越南)

    在UniToy中,我們可以按照代碼頁編碼順序查看這些代碼頁的字符和編碼:

    我們不能直接設(shè)置ANSI代碼頁,只能通過選擇系統(tǒng)Locale,間接改變當(dāng)前的ANSI代碼頁。微軟定義的Locale只使用自己定義的代碼頁。所以,我們雖然可以通過“區(qū)域和語言選項(xiàng)”中的代碼頁轉(zhuǎn)換表安裝很多代碼頁,但只能將微軟的代碼頁作為系統(tǒng)默認(rèn)代碼頁。

    2.1.3 代碼頁轉(zhuǎn)換表

    在Windows 2000以后,Windows統(tǒng)一采用UTF-16作為內(nèi)部字符編碼。現(xiàn)在,安裝一個(gè)代碼頁就是安裝一張代碼頁轉(zhuǎn)換表。通過代碼頁轉(zhuǎn)換表,Windows既可以將代碼頁的編碼轉(zhuǎn)換到UTF-16,也可以將UTF-16轉(zhuǎn)換到代碼頁的編碼。代碼頁轉(zhuǎn)換表的具體實(shí)現(xiàn)可以是一個(gè)以nls為后綴的數(shù)據(jù)文件,也可以是一個(gè)提供轉(zhuǎn)換函數(shù)的動(dòng)態(tài)鏈接庫。有的代碼頁是不需要安裝的。例如:Windows將UTF-7和UTF-8分別作為代碼頁65000和代碼頁65001。UTF-7、UTF-8和UTF-16都是基于Unicode的編碼方案。它們之間可以通過簡(jiǎn)單的算法直接轉(zhuǎn)換,不需要安裝代碼頁轉(zhuǎn)換表。

    在安裝過一個(gè)代碼頁后,Windows就知道怎樣將該代碼頁的文本轉(zhuǎn)換到Unicode文本,也知道怎樣將Unicode文本轉(zhuǎn)換成該代碼頁的文本。例如:UniToy有導(dǎo)入和導(dǎo)出功能。所謂導(dǎo)入功能就是將任一代碼頁的文本文件轉(zhuǎn)換到Unicode文本;導(dǎo)出功能就是將Unicode文本轉(zhuǎn)換到任一指定的代碼頁。這里所說的代碼頁就是指系統(tǒng)已安裝的代碼頁:

    其實(shí),如果全世界人民在計(jì)算機(jī)剛發(fā)明時(shí)就統(tǒng)一采用Unicode作為字符編碼,那么代碼頁就沒有存在的必要了。可惜在Unicode被發(fā)明前,世界各國人民都發(fā)明并使用了各種字符編碼方案。所以,Windows必須通過代碼頁支持已經(jīng)被廣泛使用的字符編碼。從這種意義看,代碼頁主要是為了兼容現(xiàn)有的數(shù)據(jù)、程序和習(xí)慣而存在的。

    2.1.4 SBCS、DBCS和MBCS

    SBCS、DBCS和MBCS分別是單字節(jié)字符集、雙字節(jié)字符集和多字節(jié)字符集的縮寫。SBCS、DBCS和MBCS的最大編碼長(zhǎng)度分別是1字節(jié)、兩字節(jié)和大于兩字節(jié)(例如4或5字節(jié))。例如:代碼頁1252 (ANSI-拉丁文 I)是單字節(jié)字符集;代碼頁936 (ANSI/OEM-簡(jiǎn)體中文 GBK)是雙字節(jié)字符集;代碼頁54936 (GB18030 簡(jiǎn)體中文)是多字節(jié)字符集。

    單字節(jié)字符集中的字符都用一個(gè)字節(jié)表示。顯然,SBCS最多只能容納256個(gè)字符。

    雙字節(jié)字符集的字符用一個(gè)或兩個(gè)字節(jié)表示。那么我們從文本數(shù)據(jù)中讀到一個(gè)字節(jié)時(shí),怎么判斷它是單字節(jié)字符,還是雙字節(jié)字符的首字符?答案是通過字節(jié)所處范圍來判斷。例如:在GBK編碼中,單字節(jié)字符的范圍是0x00-0x80,雙字節(jié)字符首字節(jié)的范圍是0x81到0xFE。我們順序讀取字節(jié)數(shù)據(jù),如果讀到的字節(jié)在0x81到0xFE內(nèi),那么這個(gè)字節(jié)就是雙字節(jié)字符的首字節(jié)。GBK定義雙字節(jié)字符的尾字節(jié)范圍是0x40到0x7E和0x80到0xFE。

    GB18030是多字節(jié)字符集,它的字符可以用一個(gè)、兩個(gè)或四個(gè)字節(jié)表示。這時(shí)我們又如何判斷一個(gè)字節(jié)是屬于單字節(jié)字符,雙字節(jié)字符,還是四字節(jié)字符?GB18030與GBK是兼容的,它利用了GBK雙字節(jié)字符尾字節(jié)的未使用碼位。GB18030的四字節(jié)字符的第一字節(jié)的范圍也是0x81到0xFE,第二字節(jié)的范圍是0x30-0x39。通過第二字節(jié)所處范圍就可以區(qū)分雙字節(jié)字符和四字節(jié)字符。GB18030定義四字節(jié)字符的第三字節(jié)范圍是0x81到0xFE,第四字節(jié)范圍是0x30-0x39。

    2.2 代碼頁實(shí)例

    2.2.1 實(shí)例一:GB18030代碼頁

    1.1節(jié)的“錯(cuò)誤2”中演示了一個(gè)全被顯示成'?'的文件。這個(gè)文件的數(shù)據(jù)是:

    其實(shí),這是一個(gè)包含了6個(gè)四字節(jié)字符的GB18030編碼的文件。記事本按照GBK顯示這些數(shù)據(jù),而GB18030的四字節(jié)字符編碼在GBK中是未定義的。Windows根據(jù)首字節(jié)范圍判斷出12個(gè)雙字節(jié)字符,然后因?yàn)檎也坏狡ヅ涞霓D(zhuǎn)換而將其映射到默認(rèn)字符'?'。使用UniToy按照GB18030代碼頁導(dǎo)入這個(gè)文件,就可以看到:

    這個(gè)GB18030編碼的文件是用UniToy創(chuàng)建的,編輯Unicode文本,然后導(dǎo)出到GB18030編碼格式。

    2.2.2 實(shí)例二:GBK和Big5的轉(zhuǎn)換

    綜合使用UniToy的導(dǎo)入、導(dǎo)出功能就可以在任意兩個(gè)代碼頁之間轉(zhuǎn)換文本。其實(shí),由于各代碼頁支持的字符范圍不同,我們一般不會(huì)直接在代碼頁間轉(zhuǎn)換文本。例如將以下GBK編碼的文本:

    直接轉(zhuǎn)換到Big5編碼,就會(huì)看到:

    變成'?'的字符都是Big5編碼不支持的簡(jiǎn)化字。在從Unicode轉(zhuǎn)換到Big5編碼時(shí),由于Big5編碼不支持這些字符,Windows就用默認(rèn)字符'?'代替。在UniToy中,我們可以先將簡(jiǎn)體字轉(zhuǎn)換到繁體字,然后再導(dǎo)出到Big5編碼,就可以正常顯示:

    同理,將Big5編碼的文本轉(zhuǎn)換到GBK編碼的步驟應(yīng)該是:

    • 將Big5編碼的文本導(dǎo)入到Unicode文本;
    • 將繁體的Unicode文本轉(zhuǎn)換簡(jiǎn)體的Unicode文本;
    • 將簡(jiǎn)體的Unicode文本導(dǎo)出到GBK文本。

    2.3 互聯(lián)網(wǎng)的字符集

    2.3.1 字符集

    互聯(lián)網(wǎng)上的信息繽紛多彩,但文本依然是最重要的信息載體。html文件通過標(biāo)記表明自己使用的字符集。例如:

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    或者:

    <meta http-equiv="charset" content="iso-8859-1">

    那么我們可以使用哪些字符集(charset)呢?在IETF(互聯(lián)網(wǎng)工程任務(wù)組)的網(wǎng)頁上維護(hù)著一份可以在互聯(lián)網(wǎng)上使用的字符集的清單:CHARACTER SETS。如果有新的字符集被登記,IETF會(huì)更新這份文檔。

    簡(jiǎn)單瀏覽一下,2006年12月7日的版本列出了253個(gè)字符集。其中也包括微軟的CP1250 ~ CP1258,在這里它們不會(huì)被稱作什么ANSI代碼頁,而是被簡(jiǎn)單地稱作windows-1250、windows-1251等。其實(shí)在Unicode被廣泛使用前,除了中日韓等大字符集,世界上,特別是西方使用最廣泛的字符集應(yīng)該是ISO 8859系列字符集。

    2.3.2 ISO 8859系列字符集

    ISO 8859系列字符集是歐洲計(jì)算機(jī)制造商協(xié)會(huì)(ECMA)在上世紀(jì)80年代中期設(shè)計(jì),并被國際標(biāo)準(zhǔn)化(ISO)組織采納為國際標(biāo)準(zhǔn)。ISO 8859系列字符集目前有15個(gè)字符集,包括:

    • ISO 8859-1 大部分的西歐語系,例如英文、法文、西班牙文和德文等(Latin-1)
    • ISO 8859-2 大部分的中歐和東歐語系,例如捷克文、波蘭文和匈牙利文等(Latin-2)
    • ISO 8859-3 歐洲東南部和其它各種文字(Latin-3)
    • ISO 8859-4 斯堪的那維亞和波羅的海語系(Latin-4)
    • ISO 8859-5 拉丁文與斯拉夫文(俄文、保加利亞文等)
    • ISO 8859-6 拉丁文與阿拉伯文
    • ISO 8859-7 拉丁文與希臘文
    • ISO 8859-8 拉丁文與希伯來文
    • ISO 8859-9 為土耳其文修正的Latin-1(Latin-5)
    • ISO 8859-10 拉普人、北歐與愛斯基摩人的文字(Latin-6)
    • ISO 8859-11 拉丁文與泰文
    • ISO 8859-13 波羅的海周邊語系,例如拉脫維亞文等(Latin-7)
    • ISO 8859-14 凱爾特文,例如蓋爾文、威爾士文等(Latin-8)
    • ISO 8859-15 改進(jìn)的Latin-1,增加遺漏的法文、芬蘭文字符和歐元符號(hào)(Latin-9)
    • ISO 8859-16 羅馬尼亞文(Latin-10)

    其中缺少的編號(hào)12據(jù)說是為了預(yù)留給天城體梵文字母(Deva-nagari)的。印地文和尼泊爾文都使用了這種在七世紀(jì)形成的字母表。由于印度定義了自己的編碼ISCII(Indian Script Code for Information Interchange),所以這個(gè)編號(hào)就未被使用。ISO 8859系列字符集都是單字節(jié)字符集,即只使用0x00-0xFF對(duì)字符編碼。

    大家都知道ASCII吧,那么大家知道ANSI X3.4和ISO 646嗎?在1968年發(fā)布的ANSI X3.4和1972年發(fā)布的ISO 646就是ASCII編碼,只不過是不同組織發(fā)布的。絕大多數(shù)字符集都與ASCII編碼保持兼容,ISO 8859系列字符集也不例外,它們的0x00-0x7f都與ASCII碼保持一致,各字符集的不同之處在于如何利用0x80-0xff的碼位。使用UniToy可以查看ISO 8859系列所有字符集的編碼,例如:

    通過這些演示,大家是不是覺得代碼頁和字符集都是很簡(jiǎn)單、樸實(shí)的東西呢?好,在進(jìn)入U(xiǎn)nicode的話題前,讓我們先看一個(gè)很深?yuàn)W的概念。

    posted @ 2011-05-12 21:56 RTY 閱讀(782) | 評(píng)論 (0)編輯 收藏

         摘要: 字符集編碼與 C/C++ 源文件字符編譯亂彈 2010年2月24日Breaker原創(chuàng)發(fā)表評(píng)論閱讀評(píng)論 最近在看國際化編程 (i18n: internationalization) 的東西,也弄清楚了點(diǎn)字符集有關(guān)的一些問題,其實(shí)網(wǎng)上的一些牛人已經(jīng)將字符集、Unicode 等相關(guān)的問題說的很清楚了,我在這里引用他們的總結(jié)并自己小結(jié)一下心得,并且實(shí)驗(yàn)一下在編譯時(shí),源代碼自身的字...  閱讀全文

    posted @ 2011-05-12 21:40 RTY 閱讀(2318) | 評(píng)論 (4)編輯 收藏

    僅列出標(biāo)題
    共31頁: First 20 21 22 23 24 25 26 27 28 Last 
    青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久精品夜色噜噜亚洲a∨| 在线观看久久av| 一区二区国产在线观看| 亚洲欧美日韩专区| 国产精品久久久久久五月尺| 一区二区三区视频在线观看| 麻豆精品传媒视频| 亚洲一级高清| 亚洲精品在线免费观看视频| 国产精品视频一区二区三区 | 亚洲韩日在线| 欧美顶级大胆免费视频| 久久久国产亚洲精品| 亚洲一区二区视频在线| 最新国产拍偷乱拍精品 | 亚洲欧美日韩第一区| 日韩午夜在线播放| 久久野战av| 欧美日韩成人在线观看| 欧美日韩精品综合| 国产日韩精品入口| 亚洲国产成人久久综合一区| 亚洲精品视频在线观看网站| 亚洲影院高清在线| 老司机精品视频网站| 亚洲久久视频| 久久综合激情| 国产亚洲精久久久久久| 日韩亚洲欧美成人一区| 一区二区三区精品在线| 正在播放亚洲| 久久免费高清视频| 国内精品模特av私拍在线观看| 久久女同互慰一区二区三区| 亚洲高清免费视频| 午夜伦欧美伦电影理论片| 亚洲午夜视频在线观看| 精品动漫3d一区二区三区免费| 亚洲精品在线观看免费| 欧美aⅴ一区二区三区视频| 99国产精品| 国产精品第2页| 中文一区二区| 亚洲深夜福利| 好看的日韩av电影| 亚洲精品在线观看免费| 久久精品一区二区三区不卡牛牛| 亚洲欧洲一区| 模特精品在线| 永久域名在线精品| 久久久久久久综合日本| 在线亚洲欧美| 欧美先锋影音| 亚洲视频免费在线观看| 日韩一区二区精品| 欧美视频一区二区三区四区| 欧美一区二视频| 亚洲精品自在久久| 亚洲福利视频网| 国产精品mv在线观看| 玖玖在线精品| 国产日韩欧美二区| 亚洲激情第一区| 国产精品美女在线观看| 亚洲视屏在线播放| 在线视频亚洲| 在线日本成人| 久久精品国产欧美亚洲人人爽| 亚洲美女精品久久| 亚洲欧美色婷婷| 亚洲一区二区免费| 99精品国产99久久久久久福利| 欧美日韩的一区二区| 最新国产拍偷乱拍精品| 亚洲大片免费看| 国产一区二区三区四区在线观看| 亚洲第一天堂无码专区| 国产精品一区在线播放| 亚洲电影免费观看高清| 欧美视频在线免费| 久久在线视频在线| 国产精品美女一区二区在线观看| 亚洲高清不卡av| 国产女主播在线一区二区| 亚洲欧洲日本国产| 在线日韩av| 久久麻豆一区二区| 91久久精品一区二区别| 亚洲精品乱码久久久久久黑人 | 亚洲人www| 欧美亚洲一级片| 精品成人一区二区三区| 免费看的黄色欧美网站| 久久野战av| 香蕉av777xxx色综合一区| 在线播放不卡| 久久成人精品电影| 亚洲国产精品国自产拍av秋霞| 亚洲精品视频免费观看| 国产精品露脸自拍| 久久国产精品一区二区三区四区| 欧美影院视频| 一区在线视频观看| 麻豆av一区二区三区| 久久视频这里只有精品| 亚洲电影欧美电影有声小说| 夜夜嗨av一区二区三区四季av | 夜夜躁日日躁狠狠久久88av| 亚洲一区二区三区四区五区黄| 国产伦精品一区二区三区四区免费| 欧美激情影音先锋| 91久久精品国产91久久| 国产精品每日更新在线播放网址| 一本色道久久综合精品竹菊| 久久免费视频网站| 亚洲狼人综合| 国产一区在线播放| 欧美午夜片在线免费观看| 亚洲男人的天堂在线aⅴ视频| 欧美电影免费观看大全| 久久午夜av| 久久精品视频播放| 久久激情综合网| 久久久久国内| 欧美成人一品| 黄色工厂这里只有精品| 欧美大片免费观看在线观看网站推荐| 欧美国产日本| 久久精品国产成人| 亚洲永久在线观看| 国产精品99久久久久久有的能看| 亚洲精品日本| 亚洲一区二区伦理| 亚洲欧美日韩国产成人| 亚洲专区在线视频| 欧美中文字幕在线播放| 久久人人九九| 免费精品视频| 一区二区三区 在线观看视| 亚洲一区二区三区精品动漫| 久久久国产一区二区三区| 老司机67194精品线观看| 久久不射电影网| 久久一区二区三区国产精品| 久久激情中文| 欧美精品一区二区三区在线播放| 欧美电影资源| 国产精品永久入口久久久| 一区精品在线播放| 亚洲网站在线| 亚洲精品久久| 香蕉久久国产| 国产精品久久久久秋霞鲁丝 | 亚洲精品美女久久7777777| 亚洲欧洲在线一区| 性欧美超级视频| 亚洲国产天堂网精品网站| 亚洲欧美日韩国产综合在线 | 亚洲欧美日韩系列| 亚洲人成免费| 久久久综合免费视频| 欧美激情1区2区| 亚洲综合99| 欧美日韩另类视频| 黄色av日韩| 久久综合色天天久久综合图片| 制服丝袜亚洲播放| 欧美日韩亚洲高清| 亚洲国产精品久久人人爱蜜臀| 乱人伦精品视频在线观看| 亚洲欧美在线免费观看| 国产精品一区亚洲| 免费成人av| 国产一区二区三区精品欧美日韩一区二区三区| 亚洲黄页一区| 日韩视频国产视频| 欧美福利视频在线| 日韩亚洲精品视频| 亚洲美女视频在线观看| 欧美日韩三级| 欧美国产免费| 欧美视频在线观看免费| 蜜桃av一区| 欧美日韩一区二区三区免费看| 久久久久久电影| 亚洲日本va午夜在线影院| 久久婷婷激情| 亚洲神马久久| 久久久蜜桃一区二区人| 亚洲精品婷婷| 久久激情一区| 久久国产一区二区| 久久久久久久性| 欧美亚洲视频一区二区| 欧美二区在线看| 久久99伊人| 国产精品jizz在线观看美国 | 国产精品国产成人国产三级| 欧美成人在线网站| 欧美日本在线观看|