const
的小知識:
常量指針const 變量類型* 指針名(const int* p)
有如下代碼,我們通過指針p
去修改一個(gè)變量num
的值:
void test02()
{int num = 10;
int* p = #
*p = 20; // num會(huì)被修改成20
printf("%d\n", num); // 輸出:20
}
此時(shí)如果我們對以上代碼進(jìn)行一個(gè)修改:在int* p = &num
前加上一個(gè)const
修飾,代碼如下:
void test02()
{int num = 10;
const int* p = # // const放在指針類型變量(int* p)前
*p = 20;
}
此時(shí)第5行代碼會(huì)報(bào)錯(cuò):表達(dá)式必須是可修改的左值
這是因?yàn)槲覀冊诙x指針變量p
的時(shí)候,這個(gè)const
讓這個(gè)指針p
變成了一個(gè)常量指針(理解:一個(gè)指向常量的指針,也就是說這個(gè)指針?biāo)赶虻淖兞渴且粋€(gè)常量,其值是不可用修改的;或者說我們解引用*p
訪問到的這個(gè)變量變成了一個(gè)常量,其值不可以修改)
此時(shí)*p
訪問到的是一個(gè)常量,常量無法修改,也即無法賦值,所以編譯器會(huì)報(bào)錯(cuò)如上。
快速的理解就是:我們看到了const int* p = &num
,也就等價(jià)于有const *p
,那么也就是*p
是常量,不能*p = 20
賦值修改
所以當(dāng)我們將**const
放在指針變量定義(int* p)
時(shí),指針類型(int*)
的前面,此時(shí)就可以實(shí)現(xiàn)我們所定義的這個(gè)指針p
所指向的內(nèi)容*p
不可以被賦值修改。**
還應(yīng)注意:常量指針使得我們對p
解引用*p
時(shí)無法修改*p
中的內(nèi)容,但如果我們通過num
去修改還是可以的:
void test02()
{int num = 10;
const int* p = #
// *p = 20; // 編譯器報(bào)錯(cuò):表達(dá)式必須是可修改的左值
num = 20; // num仍然可以修改
printf("%d\n", num); // 輸出:20
}
以上代碼的理解方式:
也就是說,常量指針是使得*p變成了一個(gè)常量,但
num
本身仍是一個(gè)變量。或者這樣說,在上面的代碼中,
num
中的變量值有兩種方式可以去訪問,一種是通過變量名num
,另一種是通過指針*p
,那么指針常量是使得*p
這種訪問方式下:無法修改*p
中的內(nèi)容(10),但是并沒有禁止變量名的訪問方式修改變量值。還可以這樣說,常量指針只是限制了指針訪問的這個(gè)方式/這個(gè)角度去訪問這個(gè)變量時(shí),這個(gè)變量成了一個(gè)常量,注意是在指針訪問的這個(gè)角度去看這個(gè)變量
num
時(shí)有這種效果,但實(shí)際上num
這個(gè)變量本質(zhì)上還是一個(gè)變量,所以其仍可以通過自身的變量名num
去修改其中的值
但是當(dāng)我們把代碼修改成如下時(shí):
void test02()
{const int num = 10; // const修飾變量名
int* p = # // 取消const對指針的修飾
*p = 20; // *p可以修改num中的值
// num = 20; // 報(bào)錯(cuò):表達(dá)式必須是可修改的左值
printf("%d\n", num); // 輸出:20
}
我們采用上面提到的3種理解方式中的第2種來說明這個(gè)問題:
當(dāng)我們在定義變量
num
的時(shí)候,如果在num
前加上const
就會(huì)導(dǎo)致變量名訪問變量的這種方式:無法修改num
中的變量值(10),但是此時(shí)并沒有禁止*p
的訪問方式修改變量值。
綜上所述:
const
修飾,就會(huì)導(dǎo)致相應(yīng)的變量訪問方式無法修改變量值:const
加在變量名前:const 變量類型 變量名(const int num)
就使得變量名的訪問方式變量名 = 值(num = 20)
無法修改變量值,但不限制指針(解引用)的訪問方式*指針名 = 值(*p = 20)
修改變量值。const
加在指針前:const 變量類型* 指針名(const int* p)
就使得指針(解引用)的訪問方式*指針名 = 值(*p = 20)
無法修改變量值,但不限制變量名的訪問方式變量名 = 值(num = 20)
修改變量值。*p
這種方式不可改,變量名的方式仍可以改)const 變量類型* 指針名(const int* p)
那么如果我們想使得兩種訪問方式都不能修改變量值該怎么做呢?不用說,大家肯定都想得到了,我們直接放出代碼:
void test02()
{const int num = 10; // const修飾變量名
const int* p = # // const修飾指針
// *p = 20; // 報(bào)錯(cuò):表達(dá)式必須是可修改的左值
// num = 20; // 報(bào)錯(cuò):表達(dá)式必須是可修改的左值
printf("%d\n", num);
}
我們直接在定義這些變量的時(shí)候,前面都加上const
,那么無論哪種訪問方式,它們的修改/賦值功能就都會(huì)被禁止。
那么以上是常量指針的相關(guān)知識。從上述我們知道常量指針是指針?biāo)赶虻膬?nèi)容*p
不可改,那么我們又有一個(gè)問題:既然指針?biāo)赶騼?nèi)容不可改,那**指針本身可以改嗎?**我們寫一個(gè)測試代碼,如下:
void test02()
{int num1 = 10;
int num2 = 20;
const int* p = &num1; // const修飾指針
// *p = 20; // 報(bào)錯(cuò):表達(dá)式必須是可修改的左值
p = &num2; // 可以執(zhí)行
}
可以發(fā)現(xiàn),常量指針?biāo)赶虻膬?nèi)容*p
是改不了,但是指針本身可以改,也就是說,指針的指向可以改(上面的案例中p
本來是指向num1
的,后來修改指向了num2
)
那么我們?nèi)绻胱屩羔槺旧聿豢筛模ɑ蛘哒f指針的指向不可以改),又該如何操作呢?接下來我們介紹指針常量的知識:
指針常量變量類型* const 指針名(int* const p)
對于常量指針我們的理解是:指向常量的指針。那么很自然的,指針常量的理解就應(yīng)該是說,這個(gè)指針本身就是個(gè)常量,不可以被修改。
我們觀察我們上面寫過的代碼:
const int* p = &num1;
這行代碼所定義的變量p
就被我們稱為常量指針,對比其書寫的位置也是剛剛好:先是常量const
,再是指針*
,所以被我們稱為常量指針,那么聰明的我們自然會(huì)猜測:指針常量的書寫應(yīng)該就應(yīng)該是…(注意這里所謂的書寫位置對于指針常量和常量指針的理解,有助于我們記憶和區(qū)分這兩種指針)
int* const p = &num1;
這樣?…
沒錯(cuò),指針常量還真就是這樣!其定義語法就是:變量類型* const 指針名(int* const p)
此時(shí)如果我們在程序中定義這樣的指針常量:
void test02()
{int num1 = 10;
int num2 = 20;
int* const p = &num1; // 定義指針常量
*p = 20; // 可以執(zhí)行
// p = &num2; // 報(bào)錯(cuò):表達(dá)式必須是可修改的左值
}
會(huì)發(fā)現(xiàn)指針p
(是一個(gè)指針常量)本身是無法修改的(也即其指向是無法修改的),但是其指向的內(nèi)容*p
可以訪問和修改
這就是指針常量:指針本身(或者說指針的指向)無法修改
快速區(qū)分方法對比常量指針和指針常量的定義語法,我們?nèi)绾慰焖俚刈⒁夂蛥^(qū)分這兩者的稱謂和功能呢?
常量指針:const 變量類型* 指針名(const int* p)
指針常量:變量類型* const 指針名(int* const p)
1.首先最容易的就是通過我們上面說到過的書寫位置:
常量指針的const
是放在*
前的,所以我們按照這樣的書寫順序就可以稱之為:常量const
指針*
而指針常量的*
是放在const
后的,所以我們同樣按照書寫順序就可以稱之為:指針*
常量const
2.上面區(qū)分了二者的叫法,那又如何快速區(qū)分二者的功能呢?如下:
const 變量類型* 指針名(const int* p)
,省略中間的int
,簡化之后就是const *p
,也就是說*p
就是個(gè)常量,不可以修改。也就是我們上面說的:常量指針?biāo)赶虻膬?nèi)容是常量,不可以修改。? 但此時(shí)p
本身可以修改,原因就是const
修飾的是*p
,而不是p
。
變量類型* const 指針名(int* const p)
,簡化之后就是const p
,也就是說p是個(gè)常量,不可以修改,也同樣對應(yīng)我們上面說的:指針常量本身(或者說指針的指向)不可用修改。? 但此時(shí)*p
的內(nèi)容可以修改,原因就是const
修飾的是p
,而不是*p
。
那么由以上的知識我們可以繼續(xù)思考,如果要使得一個(gè)指針p不僅所指向的內(nèi)容*p
不可修改,其本身p(其指向)不可修改又該如何做呢?相信大家肯定都想得到,這里我們直接放出代碼:
void test02()
{int num1 = 10;
int num2 = 20;
const int* const p = &num1; // p即是常量指針,又是指針常量,它同時(shí)具有兩種這兩種指針的特點(diǎn)
// *p = 20; // 報(bào)錯(cuò):表達(dá)式必須是可修改的左值
// p = &num2; // 報(bào)錯(cuò):表達(dá)式必須是可修改的左值
}
可以看到此時(shí)無論是我們?nèi)バ薷闹羔標(biāo)赶虻膬?nèi)容或者修改指針本身都會(huì)報(bào)錯(cuò),也就是說兩者都改不了!
以上是我關(guān)于指針常量和常量指針的個(gè)人小見解,內(nèi)容總結(jié)自比特鵬哥的C語言教學(xué)視頻:25.VS環(huán)境-C語言實(shí)用調(diào)試技巧(2)嗶哩嗶哩_bilibili
加上一些個(gè)人的思考和理解,有什么問題歡迎大家批評指正~
也歡迎大家任何的想法和知識交流!
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧