指針變量和它所指向的內(nèi)存空間是兩個不同的概念
由于Const在C和C++中存在差異拄踪,本篇將會對Const
在兩種語言的表現(xiàn)異同點上進行對比探討币厕。
實現(xiàn)方式不同
在C語言中狐援,Const
修飾的變量只是告訴編譯器該變量是一個只讀的變量栏账,不能通過該變量改寫器內(nèi)存空間中的值梁钾,但是其本質(zhì)上還是一個變量,既然是變量祭往,就會有內(nèi)存地址伦意,因此可以通過指針間接修改該地址空間的值。
const int a = 10;
int* p = &a;
*p = 20;
printf("a = %d, *p = %d\n", a, *p);
-------------結果------------------
a = 20, *p = 20
在C++中Const
修飾的變量被稱為常量硼补,其值存放在常量表中驮肉,在使用常量時,編譯器回到常量表中查詢對應的常量已骇,并將其替換离钝,這部分沒有涉及內(nèi)存分配,因此對其取地址是沒有意義的褪储。但是當我們非要對該常量去地址時卵渴,則編譯器會為其臨時分配一個內(nèi)存,并將常量值存入該臨時內(nèi)存中鲤竹,事實上浪读,在C++中規(guī)定必須用const修飾的指針來指向const修飾的常量。雖然可以使用強制轉換的方式辛藻,對Const
修飾的常量進行去地址碘橘,并將其賦值給一個非Const
修飾的指針(最好不要這樣做),但打這個指針上的任何改動都只會影響到臨時分配的內(nèi)存空間吱肌,而不會影響到原常量上蛹屿。
const int a = 10;
int* p = (int *)&a;
*p = 20;
printf("a = %d, *p = %d\n", a, *p);
-------------結果------------------
a = 10, *p = 20
變量的文件作用域
在C語言中,訪問一個變量之前岩榆,該變量必須要被預先定義错负,當訪問一個由外部文件定義的變量時,則必須要提前聲明該變量勇边。來看下面幾個例子犹撒。
// main.c
extern int a;
int main() {
printf("a = %d\n", a);
return 0;
}
//ln_const.c
int a = 128;
--------結果-------
a = 128
上面的例子是一個標準C語言訪問外部變量的例子。我們編寫代碼時也應該遵守這樣的規(guī)則粒褒。但是识颊,總有寫人不是那么規(guī)范,例如可以在main.c
文件中將extern
關鍵字去掉奕坟。
// main.c
int a;
int main() {
printf("a = %d\n", a);
return 0;
}
//ln_const.c
int a = 128;
--------結果-------
a = 128
我們發(fā)現(xiàn)實際上結果并沒有變化祥款,因為編譯器在編譯時,如果在當前文件中該變量沒有被定義月杉,則會從其他文件中尋找定義并鏈接刃跛。因此結果是沒有問題的。那么如果變量a的定義被設定成文件內(nèi)私有時苛萎,將會發(fā)生什么呢桨昙?
// main.c
int a;
int main() {
printf("a = %d\n", a);
return 0;
}
// ln_const.c
static int a = 128;
--------結果-------
a = 0
發(fā)生這種現(xiàn)象的原因是检号,編譯器沒有找到該變量的外部定義,則直接將聲明默認為定義蛙酪,因此變量a是一個默認賦值齐苛。事實上extern
關鍵字的作用就是,告訴編譯器桂塞,該變量的值是由外部文件定義的凹蜂。因此當我們聲明一個外部變量時,如果編譯器無法再外部找到該變量的定義阁危,則會無法編譯通過炊甲。
// main.c
extern int a;
int main() {
printf("a = %d\n", a);
return 0;
}
// ln_const.c
static int a = 128;
--------結果-------
編譯失敗,無法解析外部符號a
那么如果我們在外部定義了一個Const
變量欲芹,情況是否會有不同呢?在標準情況下吟吝,聲明和定義菱父,應該是保持一致的。因此標準做法應該是這樣的剑逃。
// main.c
extern const int a ;
int main() {
printf("a = %d\n", a);
return 0;
}
// ln_const.c
const int a = 128;
-----結果---------
a = 128
C語言的難點之一就是規(guī)范標準浙宜,總有人會在聲明時忘記const
關鍵字,但是結果也是正確的蛹磺。
// main.c
extern int a ;
int main() {
printf("a = %d\n", a);
return 0;
}
// ln_const.c
const int a = 128;
-----結果---------
a = 128
既然a在聲明時并沒有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;
-----結果---------
編譯失敗萤捆,運行時異常
這里裙品,我們可以看出,變量的聲明幫助編譯器進行語法檢查俗或,但變量的定義決定了運行時的行為市怎。
當static
關鍵字和Const
關鍵字同時修飾變量時,Const
是否會修改變量的文件作用域呢辛慰?
// main.c
extern int a ;
int main() {
printf("a = %d\n", a);
return 0;
}
// ln_const.c
static const int a = 128;
-----結果---------
編譯失敗区匠,無法解析外部符號a
總結:在C語言中,變量文件作用域一般都是外部鏈接帅腌,除非使用static關鍵字修飾驰弄,Const關鍵字并不會改變變量的文件作用域