深入了解C語(yǔ)言中的const和指針
前言
文章內(nèi)容由閱讀《C專家編程》整理而來(lái)。希望可以幫助大家解決在指針賦值和const方面的問(wèn)題,也希望大家多多指正文章中的錯(cuò)誤,共同進(jìn)步。

指針的賦值
問(wèn)題
將一個(gè)類型為 char** 的值賦值給一個(gè) const char** 類型的對(duì)象是否合法呢?
先說(shuō)結(jié)果,在vs的環(huán)境下,編譯器不會(huì)報(bào)錯(cuò)也不會(huì)有任何警告。
但在linux環(huán)境下用gcc編譯就會(huì)出現(xiàn)下面的警告:
warning: assignment from incompatible pointer type
警告:來(lái)自不兼容指針類型的賦值
為了代碼的可移植性我們顯然不能寫(xiě)出這樣的代碼,下面就讓我們一步步探索這其中的奧妙。
首先來(lái)了解ANSI C有關(guān)標(biāo)準(zhǔn)
ANSI C 有關(guān)簡(jiǎn)單賦值的標(biāo)準(zhǔn)
要使賦值形式合法,必須滿足下列條件之一:
1.兩個(gè)操作數(shù)都是指向有限定符或無(wú)限定符的相容類型的指針
2. 左邊指針?biāo)赶虻念愋捅仨毦哂杏疫呏羔標(biāo)赶蝾愋偷娜肯薅ǚ?/p>
還有一個(gè)關(guān)于類型的說(shuō)明:
const float* 類型不是一個(gè)有限定符的類型——它的類型是 “指向一個(gè)具有 const 限定符的 float 類型的指針”,也就是說(shuō) const 限定符是修飾指針?biāo)赶虻念愋停皇侵羔槺旧怼?/p>
問(wèn)題解決
在解決問(wèn)題之前,我們先來(lái)看一組簡(jiǎn)單的。
char* 和 const char*
char* 和 const char* 是匹配的。它之所以合法,是因?yàn)樵谙旅娴拇a中:
char* cp; const char* cpp; cpp = cp;
- 左操作數(shù)是一個(gè)指向有const限定符的char的指針;
- 右操作數(shù)是一個(gè)指向沒(méi)有限定符的char的指針;
- char類型與char類型是相容的,左操作數(shù)所指向的類型具有右操作數(shù)所指向類型的限定符(無(wú)),再加上自身的限定符(const)。
注意,反過(guò)來(lái)就不能進(jìn)行賦值。
char* cp; const char* cpp; cp = cpp; //此時(shí)左操作數(shù)不具有右操作數(shù)的const限定符
char** 和 const char**
由上面的知識(shí)我們可以得知,char** 和 const char** 都是沒(méi)有限定符的指針類型,但他們的指向的類型不一樣(前者指向char*,后者指向const char*),這違反了上面賦值標(biāo)準(zhǔn)的第一條,所以它們是不相容的。
用這種方式理解這個(gè)有一點(diǎn)困難。可以用下面這種方法進(jìn)行理解:
char** pp1; const char** pp2; pp2 = pp1;
- 左操作數(shù)的類型是 const char**,它是一個(gè)指向 const char* 類型的指針,而 const char* 是一個(gè)沒(méi)有限定符的指針,它指向一個(gè)帶有 const 限定的 char 類型;
- 右操作數(shù)的類型是 char**,它是一個(gè)指向 char* 的指針,而 char* 是一個(gè)沒(méi)有限定符的指針,它指向一個(gè)沒(méi)有限定符的 char 類型。
const char* 和 char* 是相容的,而且他們本身沒(méi)有限定符,所以符合標(biāo)準(zhǔn)的約束條件,兩者之間的賦值是合法的。但 const char** 和 char** 之間的關(guān)系又有不同,雖然二者都沒(méi)有限定符,但二者所指向的對(duì)象類型不相容,所以不能進(jìn)行賦值。
const修飾
const修飾變量
首先,關(guān)鍵字const并不能把變量變成常量!在一個(gè)符號(hào)前加上const限定符只是表示這個(gè)符號(hào)不能被賦值。也就是說(shuō)const修飾的變量是只讀的,不可以被直接修改,但它不能防止被間接修改。
例如:
#include <stdio.h>
int main()
{
?? ?const int i = 10;
?? ?int* p = &i;
?? ?printf("before:%d\n", i);
?? ?*p = 20;
?? ?printf("after:%d\n", i);//這里打印值變成了20,說(shuō)明可以間接修改
?? ?return 0;
}const修飾指針
const修飾指針變量有多種位置,下面我們將逐個(gè)介紹。
const int* p
注:const int* p 與 int const p 寫(xiě)法不同,作用是一樣的。
這種寫(xiě)法的意思是:const修飾p,不能通過(guò)解引用(p)的方式直接修改所指向的變量,但可以通過(guò)改變指針指向的方式來(lái)修改p。
例如:
#include <stdio.h>
int main()
{
?? ?//通過(guò)下方直接解引用的方式來(lái)修改編譯器會(huì)直接報(bào)錯(cuò)
?? ?//int i = 10;
?? ?//const int* p = &i;
?? ?//*p = 20;
?? ?int i = 10;
?? ?const int* p = &i;
?? ?printf("before:%d\n", *p);
?? ?int j = 20;
?? ?p = &j;//通過(guò)這樣改變p的指向,可以間接修改*p值
?? ?printf("after:%d\n", *p);
?? ?
?? ?return 0;
}int* const p
這種寫(xiě)法的意思是:const修飾p,不能通過(guò)改變指針指向的方式修改*p的值,但可以通過(guò)解引用(*p)的方式直接修改所指向的變量。
例如:
#include <stdio.h>
int main()
{
?? ?int i = 10;
?? ?int* const p = &i;
?? ?printf("before:%d\n", *p);
?? ?*p = 20;//不能改變p的指向,但可以直接解引用修改值
?? ?printf("after:%d\n", *p);
?? ?return 0;
}const int* const p
這種寫(xiě)法是同時(shí)修飾p和*p,既不能改變p的指向,也不能用解引用直接修改。
到此這篇關(guān)于深入了解C語(yǔ)言中的const和指針的文章就介紹到這了,更多相關(guān)C語(yǔ)言const 指針內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c++內(nèi)聯(lián)函數(shù)(inline)使用詳解
這篇文章主要介紹了c++內(nèi)聯(lián)函數(shù)(inline)使用詳解,需要的朋友可以參考下2014-04-04
如何在程序中判斷VS的版本(實(shí)現(xiàn)方法詳解)
下面小編就為大家?guī)?lái)一篇如何在程序中判斷VS的版本(實(shí)現(xiàn)方法詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05
C語(yǔ)言菜鳥(niǎo)基礎(chǔ)教程之單精度浮點(diǎn)數(shù)與雙精度浮點(diǎn)數(shù)
在C語(yǔ)言中,單精度浮點(diǎn)數(shù)(float)和雙精度浮點(diǎn)數(shù)(double)類型都是用來(lái)儲(chǔ)存實(shí)數(shù)的,雙精度是用記憶較多,有效數(shù)字較多,數(shù)值范圍較大。2017-10-10
C語(yǔ)言基于EasyX實(shí)現(xiàn)貪吃蛇
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言基于EasyX實(shí)現(xiàn)貪吃蛇,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
C++四種強(qiáng)制轉(zhuǎn)換原理與價(jià)值
這篇文章主要介紹了C++的四種強(qiáng)制轉(zhuǎn)換原理與價(jià)值,文中介紹的非常詳細(xì),對(duì)學(xué)習(xí)C語(yǔ)言有一定的參考價(jià)值,感興趣的小伙伴可以參考一下2023-04-04

