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

字符字面量

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

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

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

備注:一般來說,數(shù)據(jù)值對應的是右值,而存儲位置對應的是左值,也就是變量悯周;

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

char類型和字符字面量

其實這個問題就是上面同一個問題,換了一種問題描述而已挪蹭。

因為在C中的聲明一個char類型的變量就是一個左值(存儲位置),它僅僅在char類型的變量對應的內(nèi)存空間中保存字符字面量對應的ASCII編碼的int類型的值而已.例如:

char c='A';

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

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


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

字符字面量:C vs C++

我們來考慮一下兩個簡單的代碼

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

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

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

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

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

char kiss_me(char c); 

int kiss_me(int c);


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

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

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

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

ss17.png

字面量池的特征

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

  • 不允許有重復的字符串字面量出現(xiàn)怎炊,這樣做的目的是為了節(jié)省空間,例如"hello word"不可能出現(xiàn)兩次,但“hello world ”,注意后者的字符字面量最后是一個空格即
    char s[]=['h','e','l','l','o',' ','\0'];  
    
    因此被字面量池認為不同于前者的字符串字面量谭企。下面的例子同樣的字符串字面量出現(xiàn)了兩次,但兩個char指針都指向字面量池中同一個字符串字面量,也就是說指向其池中的內(nèi)存地址是一樣的评肆。
     int main (void){
        char *s="it-dog";
        char *b="it-dog";
        //指針s和b指向同一個字符字面量的內(nèi)存地址
        //0x557375b2b21d
    }
    
  • “字符串字面量”之間都是連貫的,每個字符串字面量之間結(jié)尾存在一個特殊字符'\0'
  • 每個字符串字面量都存在一個唯一的內(nèi)存地址,也就是說前一個字符串字面量末端字符'\0'的下一個字符字面量的內(nèi)存地址就是對應字符串字面量的內(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ū)域的變量持有的相同的字符串字面量只是一個相同的副本而已瓜挽,只要沒有聲名為常量字符串,都可以修改盹廷。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市久橙,隨后出現(xiàn)的幾起案子俄占,更是在濱河造成了極大的恐慌,老刑警劉巖淆衷,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缸榄,死亡現(xiàn)場離奇詭異,居然都是意外死亡祝拯,警方通過查閱死者的電腦和手機甚带,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來佳头,“玉大人鹰贵,你說我怎么就攤上這事】导危” “怎么了碉输?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長亭珍。 經(jīng)常有香客問我敷钾,道長,這世上最難降的妖魔是什么块蚌? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮膘格,結(jié)果婚禮上峭范,老公的妹妹穿的比我還像新娘。我一直安慰自己瘪贱,他們只是感情好纱控,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布辆毡。 她就那樣靜靜地躺著,像睡著了一般甜害。 火紅的嫁衣襯著肌膚如雪舶掖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天尔店,我揣著相機與錄音眨攘,去河邊找鬼。 笑死嚣州,一個胖子當著我的面吹牛鲫售,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播该肴,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼情竹,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了匀哄?” 一聲冷哼從身側(cè)響起秦效,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涎嚼,沒想到半個月后阱州,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡铸抑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年贡耽,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鹊汛。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡蒲赂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出刁憋,到底是詐尸還是另有隱情滥嘴,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布至耻,位于F島的核電站若皱,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏尘颓。R本人自食惡果不足惜走触,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望疤苹。 院中可真熱鬧互广,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至旅敷,卻和暖如春生棍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背媳谁。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工涂滴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人韩脑。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓氢妈,卻偏偏與公主長得像,于是被迫代替她去往敵國和親段多。 傳聞我的和親對象是個殘疾皇子首量,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359