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

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

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

面試愛問之const關(guān)鍵字

[復制鏈接]

152

主題

152

帖子

1135

積分

三級會員

Rank: 3Rank: 3

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

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

    const int a = 10;   //const修飾的全局變量放在常量區(qū)
    //1.const修飾的全局變量,即使語法通過,但是運行的時候會受到常量區(qū)的保護,段錯誤,運行失敗
    void test01()
    {
        //a = 100;   //直接修改語法不通過
        int *p = &a;
        *p = 100;    //間接修改語法通過,運行時產(chǎn)生段錯誤
        printf("a  %d
    ",a);
    }
    //2.const修飾的局部變量
    void test02()
    {
        const int b = 10;   //分配到棧上
        //b = 100;  //直接修改語法不通過
       
        //c語言下稱為偽常量
        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");   //四個輸出的結(jié)果一樣

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

    使用道具 舉報

    發(fā)表回復

    您需要登錄后才可以回帖 登錄 | 立即注冊

    本版積分規(guī)則

    關(guān)閉

    站長推薦上一條 /1 下一條


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