第2篇:C/C++中的字符字面量

字符字面量

字符常量是單引號(hào)引起來的字符序列 ,字符常量通常由一個(gè)字符組成 , 也可以包含多個(gè)字符,比如'\n',在C中字符字面量是以int類型表示的,因此字符字面量的sizeof運(yùn)算結(jié)果是4。更確切地說,在C中字符字面量是ASCII系統(tǒng)編碼對(duì)應(yīng)的索引,所以例如'a'就對(duì)應(yīng)整數(shù)37.'A'對(duì)應(yīng)的就是65.可見"C Programming Language"這本書的第35-36頁的相關(guān)文檔.

必須要提到一個(gè)概念就是數(shù)據(jù)對(duì)象(Data Objects),這里簡稱對(duì)象,這是很多寫C教程很少提到的一個(gè)概念,也不是我憑空捏造的.文獻(xiàn)來源http://www.newtonlabs.com/ic/ic_5.html
像基于C衍生出來其他高層語言所理解的"對(duì)象"是有些區(qū)別的.C中的對(duì)象更偏向于內(nèi)存模型,數(shù)據(jù)對(duì)象就是規(guī)范C中所有基本數(shù)據(jù)類型的兩個(gè)基本屬性.

  • 數(shù)據(jù)值(value):就是存儲(chǔ)在某片特定數(shù)據(jù)類型大小的內(nèi)存塊中二進(jìn)制數(shù)據(jù)的表示形式。
  • 存儲(chǔ)位置 (storage location),該存儲(chǔ)位置由操作系統(tǒng)為分配一個(gè)該位置對(duì)應(yīng)的地址

備注:一般來說,數(shù)據(jù)值對(duì)應(yīng)的是右值,而存儲(chǔ)位置對(duì)應(yīng)的是左值,也就是變量

字符字面量是數(shù)據(jù)對(duì)象中的一個(gè)數(shù)據(jù)值,C的編譯器根本不允許你這么做,因?yàn)閿?shù)據(jù)值只是在某個(gè)一字節(jié)的內(nèi)存塊中二進(jìn)制碼表示形式,所以不會(huì)存在用取址操作符(&)去獲取一個(gè)值的地址這種荒謬的說法.

char類型和字符字面量

其實(shí)這個(gè)問題就是上面同一個(gè)問題,換了一種問題描述而已。

因?yàn)樵贑中的聲明一個(gè)char類型的變量就是一個(gè)左值(存儲(chǔ)位置),它僅僅在char類型的變量對(duì)應(yīng)的內(nèi)存空間中保存字符字面量對(duì)應(yīng)的ASCII編碼的int類型的值而已.例如:

char c='A';

就告訴了C編譯器完成兩件事:

  1. 需要分配char類型該有的內(nèi)存空間(通常是8bit,但實(shí)際大小跟運(yùn)行的硬件平臺(tái)有關(guān));
  2. 在為char變量分配的內(nèi)存空間中保存ASCII碼字面量'A'對(duì)應(yīng)的整數(shù)值65(二進(jìn)制形式)


    字符字面量在內(nèi)存中的表示

字符字面量:C vs C++

我們來考慮一下兩個(gè)簡單的代碼

  • 在C中char是一個(gè)基本的數(shù)據(jù)對(duì)象,默認(rèn)1個(gè)字節(jié);
  • 在C++中同樣繼承了C的char類型,當(dāng)然默認(rèn)也是1個(gè)字節(jié);
    printf("%ld",sizeof(char));   //1個(gè)字節(jié)
    

C++中的字符字面量
下面這個(gè)代碼的輸出就非常有意思了

printf("%ld",sizeof('a'));   
  • 在C中,因?yàn)?a'本質(zhì)上就是返回ASCII編碼對(duì)應(yīng)的int類型的整數(shù)值,而該C中int默認(rèn)就是4個(gè)字節(jié).這個(gè)沒疑問.
  • 在C ++語言中,當(dāng)字符字面量被sizeof作為一個(gè)操作數(shù)時(shí),C++編譯器就會(huì)在調(diào)用代碼的上下文隱含地定義了 一個(gè)臨時(shí)char變量,并且該字符字面量對(duì)應(yīng)的編碼值保存到該臨時(shí)變量中.因此你在C++源文件中用sizeof('a')會(huì)被替換為 以下偽代碼
     char tmp='a';
      sizeof(tmp); //打印char類型變量的尺寸,而不是ASCII碼對(duì)應(yīng)int類型的尺寸
    

來源中文翻譯:窄字符字面量或原始字符文字,例如 'a'或'\ n'或'\ 13'。 這樣的字面量具有char類型,并且值等于執(zhí)行字符集中c-char表示的值。 如果c-char不能表示為執(zhí)行字符集中的單個(gè)字節(jié),則字面量具有int類型和實(shí)現(xiàn)定義的值。
文獻(xiàn)來源:https://en.cppreference.com/w/cpp/language/character_literal

其中為什么C++中要字符字面量視為一個(gè)char類型來看待其中一個(gè)例證那就是C++為了兼顧函數(shù)在面向?qū)ο缶幊伤枷胫械膬蓚€(gè)特性,就是同樣函數(shù)名稱的原型的多態(tài)重寫的這兩個(gè)特性,試想以下例子。

char kiss_me(char c); 

int kiss_me(int c);


void main(void){
     kiss_me('A'); 
     kiss_me(65);
}

作一個(gè)反證的假設(shè),如果C++將字符串字面量和C的約定是一樣的話,那么字符字面量就視為一個(gè)ASCII碼對(duì)應(yīng)的int類型的整數(shù)值,那么C++就無法分辨下面的關(guān)于kiss_me的不同函數(shù)原型了,這就很矛盾了,反證C++中要字符字面量視為一個(gè)char類型的必要性.

區(qū)分字符字面量和字符串字面量

字符串字面量即用雙引號(hào)括著的多個(gè)字符字面量就是字符字面量的序列。并且字符串字面量是存在于字面量池中,字面量池中的字符串字面量是在程序初始化的時(shí)候填出入字面量池中,其生命周期直到加載該字面串字面量的程序退出。我們可以將字面量池想象成一份“簽到表”,而字符串字面量就比喻成眾多的簽名,但這份簽到表比較特殊。

ss17.png

字面量池的特征

字面量池就是位于C/C++中內(nèi)存布局中較向低地址的一片內(nèi)存區(qū)域,這片內(nèi)存區(qū)域的通常是公開的,整個(gè)程序的上下文用到所有字符字面量都會(huì)在初始化過程中填入該池,并且全局維護(hù)整個(gè)程序上下文的唯一副本。也就是其他內(nèi)存區(qū)域用到字符串字面量副本是從該池中“初次”(注意我的用詞)拷貝過去的發(fā)源地。該池的特征如下。

  • 不允許有重復(fù)的字符串字面量出現(xiàn),這樣做的目的是為了節(jié)省空間,例如"hello word"不可能出現(xiàn)兩次,但“hello world ”,注意后者的字符字面量最后是一個(gè)空格即
    char s[]=['h','e','l','l','o',' ','\0'];  
    
    因此被字面量池認(rèn)為不同于前者的字符串字面量。下面的例子同樣的字符串字面量出現(xiàn)了兩次,但兩個(gè)char指針都指向字面量池中同一個(gè)字符串字面量,也就是說指向其池中的內(nèi)存地址是一樣的。
     int main (void){
        char *s="it-dog";
        char *b="it-dog";
        //指針s和b指向同一個(gè)字符字面量的內(nèi)存地址
        //0x557375b2b21d
    }
    
  • “字符串字面量”之間都是連貫的,每個(gè)字符串字面量之間結(jié)尾存在一個(gè)特殊字符'\0'
  • 每個(gè)字符串字面量都存在一個(gè)唯一的內(nèi)存地址,也就是說前一個(gè)字符串字面量末端字符'\0'的下一個(gè)字符字面量的內(nèi)存地址就是對(duì)應(yīng)字符串字面量的內(nèi)存地址,即&“hello word”這樣的用法在C/C++中是合法的。
    char* s="hello word";
    &"hello word" //和上面的
    printf("%lp\n",&s) //和下一條語句輸出的內(nèi)存地址是一樣的
    printf("%lp\n",&"hello word")
    
  • 字面量池中的字符串字面量是只讀的,但池外中的其他內(nèi)存區(qū)域的變量持有的相同的字符串字面量只是一個(gè)相同的副本而已,只要沒有聲名為常量字符串,都可以修改。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容