首頁 > 軟體

深入瞭解C語言中的const和指標

2022-02-16 13:01:31

前言

文章內容由閱讀《C專家程式設計》整理而來。希望可以幫助大家解決在指標賦值和const方面的問題,也希望大家多多指正文章中的錯誤,共同進步。

指標的賦值

問題

將一個型別為 char** 的值賦值給一個 const char** 型別的物件是否合法呢?

先說結果,在vs的環境下,編譯器不會報錯也不會有任何警告。

但在linux環境下用gcc編譯就會出現下面的警告:

warning: assignment from incompatible pointer type

警告:來自不相容指標型別的賦值

為了程式碼的可移植性我們顯然不能寫出這樣的程式碼,下面就讓我們一步步探索這其中的奧妙。

首先來了解ANSI C有關標準

ANSI C 有關簡單賦值的標準

要使賦值形式合法,必須滿足下列條件之一:

1.兩個運算元都是指向有限定符或無限定符的相容型別的指標

2. 左邊指標所指向的型別必須具有右邊指標所指向型別的全部限定符

還有一個關於型別的說明:

const float* 型別不是一個有限定符的型別——它的型別是 “指向一個具有 const 限定符的 float 型別的指標”,也就是說 const 限定符是修飾指標所指向的型別,而不是指標本身。

問題解決

在解決問題之前,我們先來看一組簡單的。

char* 和 const char*

char* 和 const char* 是匹配的。它之所以合法,是因為在下面的程式碼中:

char* cp;
const char* cpp;
cpp = cp; 
  • 左運算元是一個指向有const限定符的char的指標;
  • 右運算元是一個指向沒有限定符的char的指標;
  • char型別與char型別是相容的,左運算元所指向的型別具有右運算元所指向型別的限定符(無),再加上自身的限定符(const)。

注意,反過來就不能進行賦值。

char* cp;
const char* cpp;
cp = cpp; //此時左運算元不具有右運算元的const限定符

char** 和 const char**

由上面的知識我們可以得知,char** 和 const char** 都是沒有限定符的指標型別,但他們的指向的型別不一樣(前者指向char*,後者指向const char*),這違反了上面賦值標準的第一條,所以它們是不相容的。

用這種方式理解這個有一點困難。可以用下面這種方法進行理解:

char** pp1;
const char** pp2;
pp2 = pp1;
  • 左運算元的型別是 const char**,它是一個指向 const char* 型別的指標,而 const char* 是一個沒有限定符的指標,它指向一個帶有 const 限定的 char 型別;
  • 右運算元的型別是 char**,它是一個指向 char* 的指標,而 char* 是一個沒有限定符的指標,它指向一個沒有限定符的 char 型別。

const char* 和 char* 是相容的,而且他們本身沒有限定符,所以符合標準的約束條件,兩者之間的賦值是合法的。但 const char** 和 char** 之間的關係又有不同,雖然二者都沒有限定符,但二者所指向的物件型別不相容,所以不能進行賦值。

const修飾

const修飾變數

首先,關鍵字const並不能把變數變成常數!在一個符號前加上const限定符只是表示這個符號不能被賦值。也就是說const修飾的變數是唯讀的,不可以被直接修改,但它不能防止被間接修改。

例如:

#include <stdio.h>

int main()
{
    const int i = 10;
    int* p = &i;
    printf("before:%dn", i);
    *p = 20;
    printf("after:%dn", i);//這裡列印值變成了20,說明可以間接修改

    return 0;
}

const修飾指標

const修飾指標變數有多種位置,下面我們將逐個介紹。

const int* p

注:const int* p 與 int const p 寫法不同,作用是一樣的。

這種寫法的意思是:const修飾p,不能通過解除參照(p)的方式直接修改所指向的變數,但可以通過改變指標指向的方式來修改p。

例如:

#include <stdio.h>

int main()
{
    //通過下方直接解除參照的方式來修改編譯器會直接報錯
    //int i = 10;
    //const int* p = &i;
    //*p = 20;

    int i = 10;
    const int* p = &i;
    printf("before:%dn", *p);
    int j = 20;
    p = &j;//通過這樣改變p的指向,可以間接修改*p值
    printf("after:%dn", *p);
    
    return 0;
}

int* const p

這種寫法的意思是:const修飾p,不能通過改變指標指向的方式修改*p的值,但可以通過解除參照(*p)的方式直接修改所指向的變數。

例如:

#include <stdio.h>

int main()
{
    int i = 10;
    int* const p = &i;
    printf("before:%dn", *p);
    *p = 20;//不能改變p的指向,但可以直接解除參照修改值
    printf("after:%dn", *p);

    return 0;
}

const int* const p

這種寫法是同時修飾p和*p,既不能改變p的指向,也不能用解除參照直接修改。

到此這篇關於深入瞭解C語言中的const和指標的文章就介紹到這了,更多相關C語言const 指標內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com