const變量與指向常量的常量指針

C語言中的變量與常量,顧名思義,可變與恆定。

const的存在就是將變量修飾爲常量,即讓變量變爲只讀屬性。(並不是真的變爲常量)

只讀的變量

使變量屬性變爲只讀,像常量一樣無法通過賦值進行更改。

定義方式:

	const int cnum = 1024;

那麼,cnum就是類似常量的只讀變量,我們就無法再使用賦值語句對它保存的數據進行更改。

指向常量的指針:

指針本身可以更改指向,但是所指向的變量的數據不可通過解引用的方式更改。

定義方式:

	const int *pc = &cnum; 

const int 爲指向整形常量的指針,它可以改變指針pc的存儲(就是指針的指向),不可通過解引用改變指針所指數據。

以上我們是使用了指向常量的指針*pc指向了只讀的變量cnum。

如果我們這麼做:讓普通指針指向只讀變量,並對其解引用來更改數據。

        const int cnum = 1024;
        int *p = &cnum;

這是一件很矛盾的事情,cnum爲只讀屬性,但是*p爲普通指針,是可以通過p更改p所指向變量的數據的。

於是會出現Warning:賦值從指針目標類型中丟棄“const”限定符 。 也就是說出現衝突,const這個限定符號被丟棄了。cnum又變爲普通變量。

也就是說,如果我們定義的只讀變量不想被指針用解引用的方式進行修改,只能將指針定義爲指向常量的指針。

 我們再讓const修飾的指針pc指向普通變量:

        int num = 520;
        const int *pc = # 

也就是說指向常量的指針現在指向的不是隻讀變量,是普通變量,

再次指向*pc = 888;語句,會發生什麼?

答案是編譯器報錯,也即是說,如果指向常量的指針指向了變量num,也不可通過對指針pc解引的方式來改變num的數據。

既然不可以通過解引用改變普通num的值,那麼可以直接通過賦值的方式改變num嗎?

答案是可以。

總結:const int *pc:會使 通過解引用更改所指數據的方法失效,但是pc存儲的地址是可以改變的,即它可指向其它數據。

 如果讓指向常量的指針指向了變量,進行解引用更改變量同樣是會報錯的。

常量指針:

常量指針,顧名思義,就是具有常量屬性的指針。一旦定義,它的指向就無法更改的指針。

定義方式:

	int num = 520;
        int *const p = # 

將const寫在*後邊,指針類型的變量的前面,表示定義的指針變量p爲常量指針  它指向的是變量num。

常量指針本身存儲地址不可被改變但是它指向的變量是可以改變的,即可以通過解引用來改變所指變量的數據。

既然常量指針可以解引用來改變指向的值,如果我們讓常量指針指向一個只讀變量,然後使用解引用更改變量的值會怎樣? 

        int num = 520;
        int *const pc = &cnum;

        *pc = 111;

 答案是編譯器警告,上面我們提到的問題:賦值從指針目標類型中丟棄“const”限定符 , 也就是說const這個限定符號被丟棄了。 由於它指向的變量可以改變數據並被成功更改了,丟棄的const的只能是cnum從而變爲可修改常量 。

總結:int *const pc:會使自己更改指向(存儲的地址)的功能失效,但是可以對其使用解引用的方法來更該指針指向變量的數據。與const int *p正好相反。

指向常量的常量指針:

本身指向不可被更改,所指也不可被更改(通過解引用)。

定義方式:

        const int cnum = 1024;  
	const int *const pcc = &cnum; 

此種指針類型叫作指向常量的常量指針,結合前兩種指針,本身不可更改,所指也不可更改。
 即以下對它的操作都是不合法的:

        *pcc = 520 ;  //報錯 
	ppc = #   //報錯 

指向指向常量的常量指針的常量指針:

二級指針。

定義方式:

        int num = 520;
        const int *const ccp = #
        const int *const *ccpp = &ccp; //定義指向 指向常量的常量指針 的常量指針ccpp  爲二級指針 

指向 指向常量的常量指針 的常量指針爲二級指針,所以爲其賦值就只能取一級指針的地址給它了,所以我們應該先定義一級指針:指向常量的常量指針;由於定時指針ccpp時與ccp添加條件相同,ccpp具有與ccp相同的約束限制。即都是不能更改自身,所指變量也無法更改。

當需要多個const修飾時就容易記混,可以梳理一下方便理解:

const習慣上放在int*左邊,表示指針所指向的int型數據不可通過指針解引用的方式進行修改,此時指針就叫作指向常量的指針。

當const放在int *右邊,指針變量名左邊,表示修飾的是指針,指針不可被更改,此時指針叫做常量指針。

當兩個位置(指針類型及指針類型變量)前面均存在const,代表這個指針兩者皆佔,即它本身不可被改變,所指向的數據也不可通過指針被改變。

千萬不要給亂七八糟的 const 給弄暈了,記住一點:const 永遠限制緊隨着它的標識符。const int * const *q = &p; 相當於 (const int) * (const *q) = &p;,即第一個 const 限制的是 **q 的指向,第二個 const 限制的是 *q 的指向,唯有一個漏網之魚 —— q 沒有被限制。如果想要使用 const 同時限制 q、*q 和 **q,聲明應該寫成:const int * const * const q = &p。

請問 const int * const *q; 和 cosnt int const **q; 有何區別?

答:const int * const *q; 限制了 *q 和 **q 的指向,而 cosnt int const **q; 只限制了 **q 的指向。
驗證const的完整代碼:

指向常量的指針:

#include <stdio.h>

int main()
{
	int num = 520;
	const int cnum = 1024;
	const int *pc = &cnum;  //const int 爲指向整形常量的指針 它可以改變指針的存儲,不可通過解引用改變指針所指數據。 
//	int *p = &cnum; warning :賦值從指針目標類型中丟棄“const”限定符 , 也就是說const這個限定符號被丟棄了。 
	
	printf("cnum: %d,&cnum: %p\n",cnum,&cnum);
	printf("*pc: %d,pc: %p\n\n",*pc,pc);
	
	pc = &num;   //可以改變指針所指 
	printf("num: %d,&num: %p\n",num,&num);
	printf("*pc: %d,pc: %p\n\n",*pc,pc);
	
//	*pc = 888;  //即使指向了變量num 也不可通過解引用改變num數據
	num = 1024;  //可以直接通過變量來修改變量數據 
	printf("num: %d,&num: %p\n",num,&num);
	printf("*pc: %d,pc: %p\n",*pc,pc);
	
//總結:一旦定義了指向常量的指針,那麼該指針只可以修改存儲的地址,不可對其解引用來修改所指變量的數據,即使所指是本身可以修改的變量。	
	return 0;
}

常量指針:

#include <stdio.h>

int main()
{
	int num = 520;
	const int cnum = 1024;  //定義屬性爲只讀的變量cnum 
	int *const p = &num;  //將const寫在*後邊,指針類型的變量的前面,表示定義的指針變量p爲常量指針  它指向的是變量num
	int *const pc = &cnum;
	//常量指針本身存儲地址不可被改變 但是它指向的變量是可以改變的,即可以通過解引用來改變所指變量的數據。 
	
	*p =  1024;
	printf("*p = %d ,p = %p\n",*p,p);
	
//	p = &cnum;  //常量指針本身的存儲的地址不可以被改變 
 	*pc = 111; //編譯器警告:賦值從指針目標類型中丟棄“const”限定符 , 也就是說const這個限定符號被丟棄了。 它指向的變量是可以改變並且數據被成功更改了,丟棄的const的只能是cnum從而變爲可修改常量 
	printf("*pc = %d ,pc = %p\n",*pc,pc);

//總結:
//定義爲const的常量就是成爲只讀屬性。只能由指向常量的指針即const int *p (此種指針只可更改其存儲的地址,而不得對其所指的變量數據進行更改)來存儲其地址。若由普通指針或常量指針存儲其地址,const會丟失
//常量指針 

	return 0;
 } 

指向常量的常量指針:

#include <stdio.h>

int main()
{
	int num = 520;
	const int cnum = 1024;  
	const int *const pcc = &cnum;  //指向常量的常量指針 結合前兩種指針,本身不可更改,所指也不可更改。
	
	printf("*pcc = %d ,pcc = %p\n",*pcc,pcc);
	
//	*pcc = 520 ;  //報錯 
//	ppc = &num;   //報錯 
	cnum = 520; 
	return 0;
 } 

指向指向常量的常量指針的常量指針:

#include <stdio.h>

int main()
{
	int num = 520;
	
	const int *const ccp = &num;  //定義指向普通變量num的常量指針 ccp
	const int *const *ccpp = &ccp;  //定義指向 指向常量的常量指針 的常量指針ccpp  爲二級指針 
	 
	printf("*ccp: %d,  &ccp: %p\n",*ccp,ccp);  // 打印出指針ccp的指向的數據以及ccp的地址 
	printf("*ccpp: %p,  **ccpp: %d\n",*ccpp,**ccpp);  //打印出指針ccpp存儲的地址 以及 兩次解引用取得的數據 

//結果 :成功打印出ccpp指針存儲的地址,且與ccp的地址相同。 
//由於定時指針ccpp時添加條件相同,ccpp具有與ccp相同的約束限制。 
 
	return 0;
 } 



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章