C/C++:Const總結(jié)

指針變量和它所指向的內(nèi)存空間是兩個(gè)不同的概念

由于Const在C和C++中存在差異,本篇將會(huì)對(duì)Const在兩種語(yǔ)言的表現(xiàn)異同點(diǎn)上進(jìn)行對(duì)比探討。

實(shí)現(xiàn)方式不同

在C語(yǔ)言中,Const修飾的變量只是告訴編譯器該變量是一個(gè)只讀的變量,不能通過(guò)該變量改寫(xiě)器內(nèi)存空間中的值,但是其本質(zhì)上還是一個(gè)變量,既然是變量,就會(huì)有內(nèi)存地址,因此可以通過(guò)指針間接修改該地址空間的值。

const int a = 10;
int* p = &a;
*p = 20;
printf("a = %d, *p = %d\n", a, *p);
-------------結(jié)果------------------
a = 20, *p = 20

在C++中Const修飾的變量被稱(chēng)為常量,其值存放在常量表中,在使用常量時(shí),編譯器回到常量表中查詢(xún)對(duì)應(yīng)的常量,并將其替換,這部分沒(méi)有涉及內(nèi)存分配,因此對(duì)其取地址是沒(méi)有意義的。但是當(dāng)我們非要對(duì)該常量去地址時(shí),則編譯器會(huì)為其臨時(shí)分配一個(gè)內(nèi)存,并將常量值存入該臨時(shí)內(nèi)存中,事實(shí)上,在C++中規(guī)定必須用const修飾的指針來(lái)指向const修飾的常量。雖然可以使用強(qiáng)制轉(zhuǎn)換的方式,對(duì)Const修飾的常量進(jìn)行去地址,并將其賦值給一個(gè)非Const修飾的指針(最好不要這樣做),但打這個(gè)指針上的任何改動(dòng)都只會(huì)影響到臨時(shí)分配的內(nèi)存空間,而不會(huì)影響到原常量上。

const int a = 10;
int* p = (int *)&a;
*p = 20;
printf("a = %d, *p = %d\n", a, *p);
-------------結(jié)果------------------
a = 10, *p = 20

變量的文件作用域

在C語(yǔ)言中,訪問(wèn)一個(gè)變量之前,該變量必須要被預(yù)先定義,當(dāng)訪問(wèn)一個(gè)由外部文件定義的變量時(shí),則必須要提前聲明該變量。來(lái)看下面幾個(gè)例子。

// main.c
extern int a;
int main() {
    printf("a = %d\n", a);
    return 0;
}
//ln_const.c
int a = 128;
--------結(jié)果-------
a = 128

上面的例子是一個(gè)標(biāo)準(zhǔn)C語(yǔ)言訪問(wèn)外部變量的例子。我們編寫(xiě)代碼時(shí)也應(yīng)該遵守這樣的規(guī)則。但是,總有寫(xiě)人不是那么規(guī)范,例如可以在main.c文件中將extern關(guān)鍵字去掉。

// main.c
int a;
int main() {
    printf("a = %d\n", a);
    return 0;
}
//ln_const.c
int a = 128;
--------結(jié)果-------
a = 128

我們發(fā)現(xiàn)實(shí)際上結(jié)果并沒(méi)有變化,因?yàn)榫幾g器在編譯時(shí),如果在當(dāng)前文件中該變量沒(méi)有被定義,則會(huì)從其他文件中尋找定義并鏈接。因此結(jié)果是沒(méi)有問(wèn)題的。那么如果變量a的定義被設(shè)定成文件內(nèi)私有時(shí),將會(huì)發(fā)生什么呢?

// main.c
int a;
int main() {
    printf("a = %d\n", a);
    return 0;
}
// ln_const.c
static int a = 128;
--------結(jié)果-------
a = 0

發(fā)生這種現(xiàn)象的原因是,編譯器沒(méi)有找到該變量的外部定義,則直接將聲明默認(rèn)為定義,因此變量a是一個(gè)默認(rèn)賦值。事實(shí)上extern關(guān)鍵字的作用就是,告訴編譯器,該變量的值是由外部文件定義的。因此當(dāng)我們聲明一個(gè)外部變量時(shí),如果編譯器無(wú)法再外部找到該變量的定義,則會(huì)無(wú)法編譯通過(guò)。

// main.c
extern int a;
int main() {
    printf("a = %d\n", a);
    return 0;
}
// ln_const.c
static int a = 128;
--------結(jié)果-------
編譯失敗,無(wú)法解析外部符號(hào)a

那么如果我們?cè)谕獠慷x了一個(gè)Const變量,情況是否會(huì)有不同呢?在標(biāo)準(zhǔn)情況下,聲明和定義,應(yīng)該是保持一致的。因此標(biāo)準(zhǔn)做法應(yīng)該是這樣的。

// main.c
extern const int a ;
int main() {
    printf("a = %d\n", a);
    return 0;
}

// ln_const.c
const int a = 128;
-----結(jié)果---------
a = 128

C語(yǔ)言的難點(diǎn)之一就是規(guī)范標(biāo)準(zhǔn),總有人會(huì)在聲明時(shí)忘記const關(guān)鍵字,但是結(jié)果也是正確的。

// main.c
extern int a ;
int main() {
    printf("a = %d\n", a);
    return 0;
}

// ln_const.c
const int a = 128;
-----結(jié)果---------
a = 128

既然a在聲明時(shí)并沒(méi)有Const修飾是不是意味著,可以直接修改a呢?

// main.c
extern int a ;
int main() {
    a = 20;
    printf("a = %d\n", a);
    return 0;
}

// ln_const.c
const int a = 128;
-----結(jié)果---------
編譯失敗,運(yùn)行時(shí)異常

這里,我們可以看出,變量的聲明幫助編譯器進(jìn)行語(yǔ)法檢查,但變量的定義決定了運(yùn)行時(shí)的行為。

當(dāng)static關(guān)鍵字和Const關(guān)鍵字同時(shí)修飾變量時(shí),Const是否會(huì)修改變量的文件作用域呢?

// main.c
extern int a ;
int main() {
    printf("a = %d\n", a);
    return 0;
}

// ln_const.c
static const int a = 128;
-----結(jié)果---------
編譯失敗,無(wú)法解析外部符號(hào)a

總結(jié):在C語(yǔ)言中,變量文件作用域一般都是外部鏈接,除非使用static關(guān)鍵字修飾,Const關(guān)鍵字并不會(huì)改變變量的文件作用域

?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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