電子產(chǎn)業(yè)一站式賦能平臺(tái)

PCB聯(lián)盟網(wǎng)

搜索
查看: 107|回復(fù): 0
收起左側(cè)

面試愛(ài)問(wèn)之const關(guān)鍵字

[復(fù)制鏈接]

193

主題

193

帖子

1532

積分

三級(jí)會(huì)員

Rank: 3Rank: 3

積分
1532
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2023-6-29 09:32:00 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式

關(guān)注、星標(biāo)公眾號(hào),直達(dá)精彩內(nèi)容
const基本介紹const是constant的簡(jiǎn)寫(xiě),用來(lái)定義常量,如果一個(gè)變量被const修飾,那么它的值就不能再被改變。
const與define的區(qū)別
  • 1、define是預(yù)編譯指令,定義的宏是在預(yù)處理階段展開(kāi)的,而const是普通變量的定義,是只讀變量,且是在編譯運(yùn)行階段使用的。
  • 2、define定義的是常量,define定義的宏在編譯后消失了,它不占用內(nèi)存,而const定義的常變量本質(zhì)上仍然是一個(gè)變量,具有變量的基本屬性,有類(lèi)型、占用存儲(chǔ)單元,除了不能作為數(shù)組的長(zhǎng)度,用const定義的常變量具有宏的優(yōu)點(diǎn),而且使用更方便。
  • 3、define定義的對(duì)象沒(méi)有數(shù)據(jù)類(lèi)型,編譯器只能機(jī)械地進(jìn)行字符替換,沒(méi)有類(lèi)型安全檢查,即會(huì)出現(xiàn)“邊際問(wèn)題”或者是“括號(hào)問(wèn)題”。而const定義的是變量,有數(shù)據(jù)類(lèi)型。
    const作用
  • 1、可以用來(lái)修飾變量,修飾函數(shù)參數(shù),修飾函數(shù)返回值,且被const修飾的東西,都受到強(qiáng)制保護(hù),可以預(yù)防其它代碼無(wú)意識(shí)的進(jìn)行修改,從而提高了程序的健壯性(是指系統(tǒng)對(duì)于規(guī)范要求以外的輸入能夠判斷這個(gè)輸入不符合規(guī)范要求,并能有合理的處理方式。ps:即所謂高手寫(xiě)的程序不容易死);
  • 2、使編譯器保護(hù)那些不希望被修改的參數(shù),防止無(wú)意代碼的修改,減少bug;
  • 3、增強(qiáng)代碼的可讀性,給讀代碼的人傳遞有用的信息,聲明一個(gè)參數(shù),是為了告訴用戶這個(gè)參數(shù)的應(yīng)用目的。
    const用法介紹1、修飾局部變量、全局變量及字符串常量示例代碼:
    #include                                                                                                                                 
    #include
    #include

    const int a = 10;   //const修飾的全局變量放在常量區(qū)
    //1.const修飾的全局變量,即使語(yǔ)法通過(guò),但是運(yùn)行的時(shí)候會(huì)受到常量區(qū)的保護(hù),段錯(cuò)誤,運(yùn)行失敗
    void test01()
    {
        //a = 100;   //直接修改語(yǔ)法不通過(guò)
        int *p = &a;
        *p = 100;    //間接修改語(yǔ)法通過(guò),運(yùn)行時(shí)產(chǎn)生段錯(cuò)誤
        printf("a  %d
    ",a);
    }
    //2.const修飾的局部變量
    void test02()
    {
        const int b = 10;   //分配到棧上
        //b = 100;  //直接修改語(yǔ)法不通過(guò)
       
        //c語(yǔ)言下稱(chēng)為偽常量
        int *p = &b;
        *p = 100;
        printf("b  %d
    ",*p); //間接修改成功

        //int a;  偽常量是不可以初始化數(shù)組的
    }
    //3.字符串常量
    void test03()
    {
        char *p1 = "hello world";
        char *p2 = "hello world";
        char *p3 = "hello world";
       
        printf("%s
    ",p1);
        printf("%s
    ", p2);
        printf("%s
    ", p3);
        printf("%s
    ",&"hello world");   //四個(gè)輸出的結(jié)果一樣

        //p1[0] = 'z'; //不允許修改字符串常量
        printf("p1[0]   %c
    ",p1[0]);  //可以輸出
    }
       
    int main()
    {
    //  test01();
    //  test02();
        test03();
       
        return 0;
    }  
    const修飾的普通變量:定義的時(shí)候就要給它賦初值,之后哪怕是賦相同值都不行。const修飾的局部變量還是變量,直接修改編譯器報(bào)錯(cuò),可以間接修改,存放在棧區(qū),代碼塊結(jié)束時(shí)釋放。
    const修飾全局變量:直接修改編譯器報(bào)錯(cuò),間接修改編譯器也許會(huì)通過(guò),但運(yùn)行時(shí)會(huì)報(bào)錯(cuò)(段錯(cuò)誤)。const修飾的全局變量存放在全局(靜態(tài))存儲(chǔ)區(qū),編譯期最初將其保存在符號(hào)表中,第一次使用時(shí)為其分配內(nèi)存,在程序結(jié)束時(shí)釋放。
    const修飾字符串常量:字符串常量位于文字常量區(qū)(也有文章歸類(lèi)于代碼區(qū)),本身就不允許被修改,如果沒(méi)有const的修飾,我們可能會(huì)在后面有意無(wú)意的修改字符串常量,這樣會(huì)導(dǎo)致對(duì)只讀內(nèi)存區(qū)域的賦值,然后程序會(huì)立刻異常終止。有了const,這個(gè)錯(cuò)誤就能在程序被編譯的時(shí)候就立即檢查出來(lái),這就是const的好處。讓邏輯錯(cuò)誤在編譯期被發(fā)現(xiàn)。
    2、修飾指針常量指針和指針常量傻傻分不清楚,以下方法幫助你來(lái)區(qū)分二者:區(qū)分常量指針和指針常量的關(guān)鍵就在于星號(hào)的位置,我們以星號(hào)為分界線。
  • 如果const在星號(hào)的左邊,則為常量指針
  • 如果const在星號(hào)的右邊則為指針常量如果我們將星號(hào)讀作‘指針’,將const讀作‘常量’的話,內(nèi)容正好符合。
  • int const * num;是常量指針,就是*num指向的數(shù)據(jù)不可以改,num指向的地址可以修改,
  • int const num;是指針常量,就是num指向的地址不可以修改,num指向的數(shù)據(jù)可以修改。代碼示例:
    //第一種,常量指針
    const int *p1;      //p本身不是const的,而p指向的變量是const
    int const *p2;      //p本身不是const的,而p指向的變量是const
    #include
    int main()
    {
        int a = 5;
        int b = 20;
        const int *p = &a;
    //  *p = 100;   //編譯器報(bào)錯(cuò)
        p = &b;     //完全可以
        printf("%d
    ",*p); //間接修改成功                                                                                                              
        return 0;
    }
    需要注意的是以下兩點(diǎn):
    1、常量指針說(shuō)的是不能通過(guò)這個(gè)指針改變變量的值,但是還是可以通過(guò)其他的方式來(lái)改變變量的值的。
    2、常量指針指向的值不能改變,但是這并不是意味著指針本身不能改變,常量指針可以指向其他的地址。
    //第二種,指針常量
    int* const p3;     //p本身是const的,而p指向的變量不是const
    #include
    int main()
    {
        int a = 5;
        int b = 20;
        int *p = &a;
        int* const n = &a;
    //  n = &b;  //error: assignment of read-only variable ‘n’                                                                                                                                    
        *p = 8;
        printf("%d
    ",a);
        return 0;
    }
    指針常量是指指針本身是個(gè)常量,不能在指向其他的地址,需要注意的是,指針常量指向的地址不能改變,但是地址中保存的數(shù)值是可以改變的,可以通過(guò)其他指向該地址的指針來(lái)修改。
        //第三種
    const int* const p4;        //p本身是const的,而p指向的變量也是const
    是以上兩種的結(jié)合,指針指向的位置不能改變并且也不能通過(guò)這個(gè)指針改變變量的值,但是依然可以通過(guò)其他的普通指針改變變量的值。
    修飾函數(shù)的參數(shù)const修飾參數(shù)是為了防止函數(shù)體內(nèi)可能會(huì)修改參數(shù)原始對(duì)象。因此,有三種情況可討論:
    1、函數(shù)參數(shù)為值傳遞:
    值傳遞(pass-by-value)是傳遞一份參數(shù)的拷貝給函數(shù),因此不論函數(shù)體代碼如何運(yùn)行,也只會(huì)修改拷貝而無(wú)法修改原始對(duì)象,這種情況不需要將參數(shù)聲明為const。例如:void func(int x)不用寫(xiě)成void func(const int x)
    2、函數(shù)參數(shù)為指針:
    指針傳遞(pass-by-pointer)只會(huì)進(jìn)行淺拷貝,拷貝一份指針給函數(shù),而不會(huì)拷貝一份原始對(duì)象。根據(jù)上面對(duì)指針常量、常量指針等討論,同樣分為三種情況:
    2.1 防止修改指針指向的內(nèi)容
    典型C庫(kù)函數(shù):char *strcpy(char *dest, const char *src);
    2.2 防止修改指針指向的地址
    void swap ( int * const p1 , int * const p2 );指針p1和指針p2指向的地址都不能修改。
    2.3 防止修改指針指向的內(nèi)容和地址
    4.修飾函數(shù)的返回值1、如果函數(shù)返回值采用“值傳遞方式”,由于函數(shù)會(huì)把返回值復(fù)制到外部臨時(shí)的存儲(chǔ)單元中,加const 修飾沒(méi)有任何價(jià)值。例如把函數(shù)int GetInt(void) 寫(xiě)成const int GetInt(void)是沒(méi)有意義的。
    2、如果給以“指針傳遞”方式的函數(shù)返回值加 const 修飾,那么函數(shù)返回值(即指針)的內(nèi)容不能被修改,該返回值只能被賦給加const 修飾的同類(lèi)型指針。
    const char * GetString(void);
    char *str = GetString(); //error: conflicting types for ‘str’
    const char *str = GetString();  //這種用法才是正確的
  • 發(fā)表回復(fù)

    本版積分規(guī)則


    聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表