今天偶然想起const這一關鍵字,再加之之前幾種const修飾指針方式讓我印象深入(混淆不清),從新回顧了一下,本身對這個關鍵詞也又有了更加深入的理解,因此總結一下。數組
1、const的定義安全
const修飾的數據類型是指常類型,常類型的變量或對象的值是不能被更新的。函數
2、const的由來spa
最初的目的是爲了取代預編譯指令define,繼承define的優勢而且擯棄它的缺點。指針
舉兩個例子:調試
1.從內存角度code
1 #define MAX_D 10
2 const int MAX_C = 10; //此時保存在符號表,未分配內存
3
4 int main(void) 5 { 6 int num_d = MAX_D; //預編譯事後這句話就是int num_d = 10;(分配內存)
7 int num_c = MAX_C; //第一次MAX_C分配內存
8
9 int num_d1 = MAX_D; //預編譯替換(分配內存)
10 int num_c1 = MAX_C; //以後MAX_C就不分配內存
11
12 return 0; 13 }
2.從語句使用:(const能避免一些宏define由於括號引發的錯誤)對象
1 #define MAX_D 10 + 20
2 const int MAX_C = 10 + 20; 3 ..... 4 int num_d = MAX_D / 2; //由於宏的特性預編譯後num_d = 10 + 20 / 2
5 int num_c = MAX_C / 2; //執行後num_c = 30 / 2;
3.小結blog
3、const的使用繼承
1.修飾只讀常量,不能被改變。改變報錯。
2.修飾通常變量(const的位置能夠在類型說明符前或後)
1 int const num=2; 2 const int num=2;
3.修飾只讀數組(const的位置能夠在類型說明符前或後)
1 int const num[2]={1, 2}; 2 const int num[2]={1, 2};
4.修飾指針(四種形式)
1 const int *ptr; //ptr可變,指向對象不能變
2 int const *ptr; //ptr可變,指向對象不能變
3 int * const ptr; //ptr不可變,指向對象可變
4 const int * const ptr; //ptr都不可變
我也搞混淆了不少次,不過總結了一下,在分析就徹底ok了。
①首先咱們得知道const一次只能修飾一個變量
②而後咱們得根據就近原則,所謂「近水樓臺先得月」來判斷哪一個變量跟cosnt最近,是(*ptr)仍是ptr。
③以前也有提到const的位置能夠在類型說明符前或後。
1 const int *ptr; //const與*ptr近,與ptr遠
2 int const *ptr; //const與*ptr近,與ptr遠
3 int * const ptr; //const與ptr近,已經拆分了*ptr
4 const int * const ptr; //第二個const與ptr近,第一個const顯然與(* const ptr)近
5.修飾函數參數
1 void Fun(const int *p); //意義指針變量自己可變,p所指向的變量不可變
①告訴編譯器傳入參數不能改變,防止使用者的無心或錯誤的修改
②修飾指針傳參,就是在聲明函數內部不會改變這個指針所指向的內容。(通常是作函數輸入參數)
③補充:這也能夠只知道函數原型時能夠大概去判斷函數列表裏的輸入參數與輸出參數
6.修飾返回值
const int Fun (void); //返回值不可被改變。
4、補充
1.const常量能夠被改變(gcc環境下)
1 const int num = 5; 2 int *p = (int *)# //強制類型轉換來消除警告;
3 *p = 10; 4 printf("num = %d.\n", num); //num = 10,const類型的變量被修改
緣由:
①const在c的規定中並未有明確規定,const修飾的變量存放在哪裏
②在gcc環境下,const是經過編譯器在編譯的時候執行安全檢查,在程序運行過程當中並不會報錯。
③內存的儲存上,gcc把const類型的常量也放在了data段
④因此根據這些特性,經過強大的指針騙過編譯器就能夠改變了
5、總結
1.const的合理使用能告訴編譯器哪些變量不但願改變,防止無心的被修改,減小bug,也使代碼更嚴謹。
2.const的使用也是爲讀代碼的人傳遞頗有用的信息,間接或直接告訴使用者這個變量不該該被修改。
做者:Devil-wei