1. 程式人生 > >C++中char型別詳解

C++中char型別詳解

# 1char與字元的關係
    ##1.1char型別到底代表什麼
      提到char型別,我相信學過C/C++的並不會陌生,char型別代表一個位元組,在記憶體中有8位,所以signed char的範圍為-128~127,unsigned char的範圍為0~255。不過C++中的char到底真的指這個麼?在這之前,首先需要明白位和位元組的概念。
    ##1.2位和位元組
      在計算機中,通常8位代表1個位元組,即1byte=8bits,然而C++對於位元組的定義與此不同,這或許跟我們熟知的8bit代表1位元組截然不同。C++對位元組的定義是至少能夠容納實現的基本字符集的相鄰位組成,也就是說可能取值的範圍至少大於等於字元數目,而我們目前熟知的ASCII碼以及EBDCIC碼用8位組合足以表示,在這種字符集系統上C++的位元組確實是8位,然而在國際程式設計中採用更大的字符集比如Unicode等時,8位組合無法表示所有字元,因此一個位元組可能需要16位甚至更多,在這種系統上,C++中的一個位元組可能就不是代表8bit了,這是C++對位元組的定義,這裡我們一定不能搞混淆了。只有在常見的ASCII碼等字符集上才是如此,一個char用8位表示。
    ##1.3什麼是字符集
      字符集是多個字元的集合,比如數字,字母,符號等,比如有常見的ASCII碼,它是由美國ANSI制定的,包括常見的數字,字母等等,它通過8位二進位制數來表示某個字元,比如字元‘A’,它的10進位制數是65,16進位制數是0x41,我們用UE開啟1個文字檔案,通過16進位制檢視可以清晰的看到‘A’的值是0x41,而‘0’的10進位制數是48,它在16進位制數中是0x30。這裡的10進位制數和16進位制數代表什麼意思呢?其實不管是字母還是數字還是其它看起來奇奇怪怪的符號,在二進位制中都是儲存在一個位元組中,也就是8位。我們所看到的‘A’其實在記憶體中表示的資料為01000001,而這塊記憶體資料如果被解釋為整數,那就是65,如果是16進位制數,那就是0x41,下面來看兩個定義,這兩條定義是否等價?
    char score =65;
    char score=‘A’;
      答案是僅在ASCII碼編碼系統上才有效,因為‘A’在ASCII碼編碼方式中它的10進位制就是65,所以兩者等效,而如果在其它編碼方式中的‘A’換成了87,那麼65就可能表示的是其它字元而不是‘A’了,因此需要根據系統採用的字符集來定,這裡我們都採用ASCII碼。至於其它例如EBCDIC,Unicode等編碼方式如果有興趣繼續瞭解的話可以自行參考其它相關資料。
#2C++中的char
    ##2.1如何表示char
      正如上面寫到的,char代表一個字元,其實就是把記憶體中的某些二進位制組合代表某個字元。宣告某個字元的時候可以使用char,unsigned char 或者signed char,字元用單引號括起來,且單引號內只能有1個字元,例如
    char a=‘b’;
    unsigned char b='\032';
    signed char c='\n';
      C++中的char並不指明這個char是signed的,這點和int、long等其它整型不同,例如int、long等如果不帶unsigned則預設表示屬於signed。
對於第一種定義方式直接指明變數a是字元‘b’,變數b則通過‘\032’定義為8進製為032(10進位制就是26)的字元也就是Ctrl+Z這個字元,變數c通過轉義字元定義為換行字元。
      如果將char用作數值型別,unsigned char可以表示0~255,而signed char只能表示-128~127,如果要用1個char儲存200,那麼有些系統可以這樣做,而有些不可以。但是unsigned char都可以,因為它可以表示到255。另一方面,如果是儲存ASCII碼字元,則有沒有符號都沒關係,直接用char即可。
      可以看到我們在定義字元的時候無論通過直接字元賦值還是用其8進位制,10進位制,16進位制等都可以。其中10進位制數可以直接賦值,而8進位制,16進位制,轉義字元等需要用‘’括起來並在前面加轉義序列\才行。不過儘量推薦在可以同時使用數字轉義序列和符號轉義序列時採用符號轉義序列,因為數字表示與特定編碼方式有關,而符號表示適用於任何編碼方式。
    ##2.2通用字元名
      C++除了允許基本的源字符集外,還允許提供擴充套件的源字符集以及執行字符集,比如德國的日耳曼母音變音等等。C++有這樣一種表示特殊字元字元的機制,它獨立於任何特定的鍵盤,使用的是通用字元名。
通用字元名的用法類似於轉義序列。可以以\u或者\U大頭。\u後面跟4個16進位制數,\U後面跟8個16進位制數。這些位表示的是ISO 10646的碼點。這些擴充套件字元可以在標識名或者字串中使用,例如:
    int k\u00F6rper;
    cout<<"Let them eat g\u00F6teau.\n";
      其中\u00F6表示的字元是Ö,那麼第一個it變數就是kÖrper,第2個變數字串打印出來則是Let them eat gÖteau.
      如果系統不支付ISO 10646,則無法打印出上述的字元。C++使用通用編碼名是因為應將\u00F6解釋為Unicode碼點為U-00F6的字元。支援Unicode的編譯器會知道這表示字元Ö,但無需使用內部編碼00F6,在不同的系統中該字元的編碼可能不同。在原始碼中可使用適用於所有系統的通用編碼名,而編譯器將根據當前系統使用合適的內部編碼表示它。
      補充:Unicode編碼提供了一種表示各字符集的解決方案,ASCII碼只是其一個子集,Unicode還包括很多拉丁字元,象形文字等。到目前為止,其可以表示10萬多個符號和90多個手寫符號並在不斷髮展。Unicode給每個字元指定了一個編碼-碼點,比如U-222B,U表示這是一個Unicode字元,而222B是該字元(積分正弦符號)的碼點。ISO建立了1個小組開發ISO 10646,這也是一個對多種語言文字進行編碼的標準。
    #2.3wchar_t
      前面已經介紹過字元集了,那麼程式處理的字符集可能無法用1個8位的位元組表示,比如日文漢字系統。對於這種情況,C++處理方式有兩種:第一,編譯器廠商把char定義為16位的位元組甚至更大,第二,可以同時支援小型基本字符集和較大的擴充套件字符集。8位的char表示基本字符集,而wchar_t(寬字元型別)表示擴充套件字符集。wchar_t是一種整數型別,有足夠大的空間表示系統使用的最大擴充套件字符集,依據底層系統來實現,在一個系統中可能是unsigned short,在另外一個系統中可能是int。定義一個wchar_t型別的字元時,需要在字元前面加上字首L,比如:
    wchar_t name=L'l';
      而在C++中用cin,cout進行輸入輸出時,無法處理wchar_t型別,因為它們把輸入輸出當成char流,需要採用wcin和wcout,比如輸出寬字串:
    wcout<<L"xixi"<<endl;
    ##2.4C++11新增的char16_t和char32_t
      隨著Unicode的發展,wchar_t也不能滿足需求了,並且在計算機上進行字元和字串編碼時,僅使用Unicode碼點並不夠。C++11標準新增了兩個新增的型別,char16_t和char32_t,前者長16位,後者長32位,並且都是無符號型別。
      C++11中使用小寫u字首表示char16_t字元常量或者字串常量,使用大寫U字首表示char32_t字元常量或者字串常量,u或者U字首指明該字元的型別為char16_t還是char32_t,比如:
    char16_t ch1=u'q';
    char32_t cha2=U"\U0000022B";