C語言中const的用法

const是一個(gè)C語言的關(guān)鍵字,它限定一個(gè)變量不允許被改變。使用const在一定程度上可以提高程序的安全性和可靠性,另外,在觀看別人代碼的時(shí)候,清晰理解const所起的作用,對(duì)理解對(duì)方的程序也有一些幫助。

我們來分情況看語法上它該如何被使用。

1、函數(shù)體內(nèi)修飾局部變量。

例:

void func()

{

const int a=0;

}

首先,我們先把const這個(gè)單詞忽略不看,那么a是一個(gè)int類型的局部自動(dòng)變量,我們給它賦予初始值0。然后再看const.

const作為一個(gè)類型限定詞,和int有相同的地位。

const int a;

int const a;

是等價(jià)的。于是此處我們一定要清晰的明白,const修飾的對(duì)象是誰,是a,和int沒有關(guān)系。const 要求他所修飾的對(duì)象為常量,不可被改變,不可被賦值,不可作為左值(l-value)。

這樣的寫法也是錯(cuò)誤的。

const int a;

a=0;

這是一個(gè)很常見的使用方式:

const double pi=3.14;

在程序的后面如果企圖對(duì)pi再次賦值或者修改就會(huì)出錯(cuò)。

然后看一個(gè)稍微復(fù)雜的例子。

const int* p;

還是先去掉const 修飾符號(hào)。

注意,下面兩個(gè)是等價(jià)的。

int* p;

int *p;

其實(shí)我們想要說的是,*p是int類型。那么顯然,p就是指向int的指針。

同理

const int* p;

其實(shí)等價(jià)于

const int (*p);

int const (*p);

即,*p是常量。也就是說,p指向的數(shù)據(jù)是常量。

于是

p+=8; //合法

*p=3; //非法,p指向的數(shù)據(jù)是常量。

那么如何聲明一個(gè)自身是常量指針呢?方法 是讓const盡可能的靠近p;

int* const p;

const右面只有p,顯然,它修飾的是p,說明p不可被更改。然后把const去掉,可以看出p是一個(gè)指向 int形式變量的指針。

于是

p+=8; //非法

*p=3; //合法

再看一個(gè)更復(fù)雜的例子,它是上面二者的綜合

const int* const p;

說明p自己是常量,且p指向的變量也是常量。

于是

p+=8; //非法

*p=3; //非法

const 還有一個(gè)作用就是用于修飾常量靜態(tài)字符串。

例如:

const char* name='David';

如果沒有const,我們可能會(huì)在后面有意無意的寫name[4]='x'這樣的語句,這樣會(huì)導(dǎo)致對(duì)只讀內(nèi)存區(qū)域的賦值,然后程序會(huì)立刻異常終止。有了 const,這個(gè)錯(cuò)誤就能在程序被編譯的時(shí)候就立即檢查出來,這就是const的好處。讓邏輯錯(cuò)誤在編譯期被發(fā)現(xiàn)。

const 還可以用來修飾數(shù)組

const char s[]='David';

與上面有類似的作用。

2、在函數(shù)聲明時(shí)修飾參數(shù)

來看實(shí)際中的一個(gè)例子。

NAME

memmove -- copy byte string

LIBRARY

Standard C Library (libc, -lc)

SYNOPSIS

#include

void *

memmove(void *dst, const void *src, size_t len);

這是標(biāo)準(zhǔn)庫中的一個(gè)函數(shù),用于按字節(jié)方式復(fù)制字符串(內(nèi)存)。它的第一個(gè)參數(shù),是將字符串復(fù)制到哪里去(dest),是目的地,這段內(nèi)存區(qū)域必須是可寫。它的第二個(gè)參數(shù),是要將什么樣的字符串復(fù)制出去,我們對(duì)這段內(nèi)存區(qū)域只做讀取,不寫。于是,我們站在這個(gè)函數(shù)自己的角度來看,src 這個(gè)指針,它所指向的內(nèi)存內(nèi)所存

儲(chǔ)的數(shù)據(jù)在整個(gè)函數(shù)執(zhí)行的過程中是不變。于是src所指向的內(nèi)容是常量。于是就需要用const修飾。例如,我們這里這樣使用它。

const char* s='hello';

char buf[100];

memmove(buf,s,6); //這里其實(shí)應(yīng)該用strcpy或memcpy更好

如果我們反過來寫,

memmove(s,buf,6);

那么編譯器一定會(huì)報(bào)錯(cuò)。事實(shí)是我們經(jīng)常會(huì)把各種函數(shù)的參數(shù)順序?qū)懛?。事?shí)是編譯器在此時(shí)幫了我們大忙。如果編譯器靜悄悄的不報(bào)錯(cuò),(在函數(shù)聲明處去掉const即可),那么這個(gè)程序在運(yùn)行的時(shí)候一定會(huì)崩潰。

這里還要說明的一點(diǎn)是在函數(shù)參數(shù)聲明中const一般用來聲明指針而不是變量本身。

例如,上面的size_t len,在函數(shù)實(shí)現(xiàn)的時(shí)候可以完全不用更改len的值,那么是否應(yīng)該把len也聲明為常量呢?可以,可以這么做。我們來分析這么做有什么優(yōu)劣。

如果加了const,那么對(duì)于這個(gè)函數(shù)的實(shí)現(xiàn)者,可以防止他在實(shí)現(xiàn)這個(gè)函數(shù)的時(shí)候修改不需要修改的值(len),這樣很好。

但是對(duì)于這個(gè)函數(shù)的使用者,

1。這個(gè)修飾符號(hào)毫無意義,我們可以傳遞一個(gè)常量整數(shù)或者一個(gè)非常量整數(shù)過去,反正對(duì)方獲得的只是我們傳遞的一個(gè)copy。

2。暴露了實(shí)現(xiàn)。我不需要知道你在實(shí)現(xiàn)這個(gè)函數(shù)的時(shí)候是否修改過len的值。

所以,const一般只用來修飾指針。

再看一個(gè)復(fù)雜的例子

int execv(const char *path, char *const argv[]);

著重看后面這個(gè),argv.它代表什么。

如果去掉const,我們可以看出

char * argv[];

argv是一個(gè)數(shù)組,它的每個(gè)元素都是char *類型的指針。

如果加上const.那么const修飾的是誰呢?他修飾的是一個(gè)數(shù)組,argv[],意思就是說這個(gè)數(shù)組的元素是只讀的。那么數(shù)組的元素的是什么類型呢?是char *類型的指針.也就是說指針是常量,而它指向的數(shù)據(jù)不是。

于是

argv[1]=NULL; //非法

argv[0][0]='a'; //合法

3、全局變量。

我們的原則依然是,盡可能少的使用全局變量。我們的第二條規(guī)則 則是,盡可能多的使用const。如果一個(gè)全局變量只在本文件中使用,那么用法和前面所說的函數(shù)局部變量沒有什么區(qū)別。如果它要在多個(gè)文件間共享,那么就牽扯到一個(gè)存儲(chǔ)類型的問題。

有兩種方式。

1.使用extern

例如

extern const double pi;

const double pi=3.14;

然后其他需要使用pi這個(gè)變量的,包含file1.h

#include 'file1.h'

或者,自己把那句聲明復(fù)制一遍就好。

這樣做的結(jié)果是,整個(gè)程序鏈接完后,所有需要使用pi這個(gè)變量的共享一個(gè)存儲(chǔ)區(qū)域。

2.使用static,靜態(tài)外部存儲(chǔ)類

static const pi=3.14;

需要使用這個(gè)變量的*.c文件中,必須包含這個(gè)頭文件。

前面的static一定不能少。否則鏈接的時(shí)候會(huì)報(bào)告說該變量被多次定義。這樣做的結(jié)果是,每個(gè)包含了constant.h的*.c文件,都有一份該變量自己的copy,該變量實(shí)際上還是被定義了多次,占用了多個(gè)存儲(chǔ)空間,不過在加了static關(guān)鍵字后,解決了文件間重定義的沖突。壞處是浪費(fèi)了存儲(chǔ)空間,導(dǎo)致鏈接完后的可執(zhí)行文件變大。但是通常,這個(gè),小小幾字節(jié)的變化,不是問題。好處是,你不用關(guān)心這個(gè)變量是在哪個(gè)文件中被初始化的。

最后,說說const的作用。

const 的好處,是引入了常量的概念,讓我們不要去修改不該修改的內(nèi)存。直接的作用就是讓更多的邏輯錯(cuò)誤在編譯期被發(fā)現(xiàn)。所以我們要盡可能的多使用const。但是很多人并不習(xí)慣使用它,更有甚者,是在整個(gè)程序 編寫/調(diào)試 完后才補(bǔ)const。如果是給函數(shù)的聲明補(bǔ)const,尚好。如果是給 全局/局部變量補(bǔ)const,那么……那么,為時(shí)已晚,無非是讓代碼看起來更漂亮了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.語言中變量的實(shí)質(zhì) 要理解C指針,我認(rèn)為一定要理解C中“變量”的存儲(chǔ)實(shí)質(zhì), 所以我就從“變量”這個(gè)東西開始講起吧...
    金巴多閱讀 1,972評(píng)論 0 9
  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型。 運(yùn)用指針編程是C語言最主要的風(fēng)格之一。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,606評(píng)論 3 44
  • 注:這是第三遍讀《C語言深度解剖》,想想好像自從大學(xué)開始就沒讀完過幾本書,其中譚浩強(qiáng)的那本《C語言程序設(shè)計(jì)(第四版...
    HavenXie閱讀 1,909評(píng)論 1 6
  • 好不容易給了自己勇氣,想出去走走來調(diào)整一天的蝸居狀態(tài),可偏偏下起了小雨,只好返回家里,坐在陽臺(tái)上聆聽下雨的聲音。 ...
    Leo簡(jiǎn)說閱讀 1,006評(píng)論 2 9
  • 大年初四,溫度降下來了,街上行人很少,坐在新華書店門口的毛澤東像下,困意一陣陣地來。街心廣場(chǎng)十字路口的廣播在重復(fù)播...
    九九鷗閱讀 175評(píng)論 0 1

友情鏈接更多精彩內(nèi)容