C語言學習筆記 (001) - 常量指標與指標常量的區別(轉帖)

來源:互聯網
上載者:User

標籤:字串處理   指標常量   聲明   改變   應用   變數   編譯器   筆記   針對   

三個名詞雖然非常繞嘴,不過說的非常準確。用中國話的語義分析就可以很方便地把三個概念區分開。

一) 常量指標。

常量是形容詞,指標是名詞,以指標為中心的一個偏正結構短語。這樣看,常量指標本質是指標,常量修飾它,表示這個指標乃是一個指向常量的指標(變數)。

指標指向的對象是常量,那麼這個對象不能被更改。

在C/C++中,常量指標是這樣聲明的:

1)const int *p;

2)int const *p;

常量指標的使用要注意,指標指向的對象不能通過這個指標來修改,可是仍然可以通過原來的聲明修改,也就是說常量指標可以被賦值為變數的地址,之所以叫做常量指標,是限制了通過這個指標修改變數的值。例如:

int a = 5;

const int b = 8;

const int *c = &a; // 這是合法的,非法的是對c的使用

*c = 6; // 非法,但可以這樣修改c指向的對象的值:a = 6;

const int *d = &b; // b是常量,d可以指向b,d被賦值為b的地址是合法的

  細心的朋友在使用字串處理函數的時候,應該會注意到這些函數的聲明。它們的參數一般聲明為常量指標。例如,字串比較函數的聲明是這樣的:

int strcmp(const char *str1, const char *str2);

可是這個函數卻可以接收非常量字串。例如這段程式:

char *str1, *str2;

str1 = "abcde1234";

str2 = "bcde";

if(strcmp(str1, str2) == 0)

{

printf("str1 equals str2.");

}

str1和str2的內容顯然是可以更改的,例如可以使用“str1[0] = x;”這樣的語句把str1的內容由“abcde1234”變為“xbcde1234”。因為函數的參數聲明用了常量指標的形式,就保證了在函數內部,那 個常量不被更改。也就是說,對str1和str2的內容更改的操作在函數內部是不被允許的。(就目前的應用來看,我覺得設定常量指標就是為函數參數聲明准 備的,不然還真不知道用在什麼地方呢,呵呵!)

雖然常量指標指向的對象不能變化,可是因為常量指標是一個變數,因此,常量指標可以不被賦初始值,且可以被重新賦值。例如:

const int a = 12;

const int b = 15;

const int *c = &a; // 為了簡化代碼,很多人習慣賦初始值

const int *d;

d = &a; // 這樣當然是可以的

c = &b; // 雖然c已經被賦予初始值,可是仍然可以指向另一個變數

特點是,const的位置在指標聲明運算子*的左側。只要const位於*的左側,無論它在類型名的左邊或右邊,都聲明了一個指向常量的指標,叫做常量指標。

可以這麼想,*左側是常量,指標指向的對象是常量。

二) 指標常量

指標是形容詞,常量是名詞。這回是以常量為中心的一個偏正結構短語。那麼,指標常量的本質是一個常量,而用指標修飾它,那麼說明這個常量的值應該是一個指標。

指標常量的值是指標,這個值因為是常量,所以不能被賦值。

在C/C++中,指標常量這樣聲明:

int a;

int *const b = &a; //const放在指標聲明操作符的右側

只要const位於指標聲明操作符右側,就表明聲明的對象是一個常量,且它的內容是一個指標,也就是一個地址。上面的聲明可以這麼讀,聲明了一個常量b,它的值是變數a的地址(變數a的地址,不就是指向變數a的指標嗎)。

因為指標常量是一個常量,在聲明的時候一定要給它賦初始值。一旦賦值,以後這個常量再也不能指向別的地址。

雖然指標常量的值不能變,可是它指向的對象是可變的,因為我們並沒有限制它指向的對象是常量。

因此,有這麼段程式:

char *a = "abcde1234";

char *b = "bcde";

char *const c = &a;

  下面的操作是可以的。

  a[0] = ‘x‘; // 我們並沒有限制a為常量指標(指向常量的指標)

或者

*c[0] = ‘x‘ // 與上面的操作一致

三)指向常量的指標常量

顧名思議,指向常量的指標常量就是一個常量,且它指向的對象也是一個常量。

因為是一個指標常量,那麼它指向的對象當然是一個指標對象,而它又指向常量,說明它指向的對象不能變化。

在C/C++中,這麼聲明:

  const int a = 25;

const int * const b = &a;

看,指標聲明操作符左邊有一個const,說明聲明的是一個指向常量的指標。再看,指標聲明操作符右邊有一個const,說明聲明的是一個指標常量。前後都鎖死了,那麼指向的對象不能變,指標常量本身也不能變。細細體味,相信能得其道,下面就不贅述了。

用一個例子作為總結。雖然字元指標與其它指標的本質是一樣的,可是因為字元指標常用來表示字串,常不好理解。下面就用字元指標來舉例。

char *a = "abcde1234";

const char *b = "bcde"; // b是指向常量字串的指標變數

char *const c = &a;  // c是指向字元指標變數的常量

const char *const d = &b; // d是指向字元常量的指標常量

問題來了。

1)問:因為a是變數,a可以賦值為其它值,如"12345abc"。那麼c指向a,當a變化了,c指向什麼呢?

答:仍然指向"abcde1234"。雖然a可以指向別的字串,可是c仍然指向"abcde1234",也就是a開始指向的對象。

2)問:a是變數,可以改變a的內容。那麼當執行了“a[0] = ‘x‘;”後,c會怎樣呢?

答:c當然還指向a初始指向的字元。不過,這個字元已經變成了‘x‘。

3)問:b是指向常量的指標變數,當b指向別的字串,d怎麼樣?

答:d仍然指向b初始的字串。

4)問:b可以變化,b指向的字元不能變化,也就是說b[0]不能被重新賦值,可是b[1]可以被重新賦值嗎?

答:原則上b指向的字元是常量,並沒有限制下一個字元,應該可以被賦值。可是因為你使用字串進行了初始賦值,而且編譯器是靜態編譯的,C/C++程式就把b當作字串指標來處理了,因此,當對下一個字元進行賦值時,編譯不能通過。

其他問題,歡迎補充。

我編了這樣的口訣,記住,應該不難:

const(*號)左邊放,我是指標變數指向常量;

const(*號)右邊放,我是指標常量指向變數;

const(*號)兩邊放,我是指標常量指向常量;

指標變數能改指向,指標常量不能轉向!

要是全都變成常量,鎖死了,我不能轉向,你也甭想變樣!

C語言學習筆記 (001) - 常量指標與指標常量的區別(轉帖)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.