C語言中的const一直是C語言初學者心中的痛,這是因為const在不同位置有不同作用,在不同情景有不同角色。這讓初學者摸不清頭腦。今天,和大家一起研究一下const,讓它的每個角色都“深入人心”!
==============================================================================================
情景一:最簡單的const用法
#include<stdio.h>
int main()
{
int const a;
a=5;
printf("a=%d\n",a);
return 0;
}如果編譯這個c文件,就會報錯:
1071.c: In function ‘main’:
1071.c:5: error: assignment of read-only variable ‘a’
顯而易見,這是const在搞鬼,因為聲明了const的變量是不能修改的!
如果將源代碼修改為如下這樣,就沒有問題了!
#include<stdio.h>
int main()
{
int const a=5;
printf("a=%d\n",a);
return 0;
}總結:const聲明的變量必須要進行初始化賦值,如果錯過這個機會,以後再想給const的變量賦值,可就沒門了!切記~
PS:int const和const int是一回事,“顛倒寫”都是可以的。以後遇到了別犯暈,呵呵。但是,還是要留個心眼,當const和指針攙和到一起時,這個“顛倒寫”的規律可未必成立。
==============================================================================================
情景二:發明const為了什麼?
在const誕生之前,開發者一直使用#define VAR 100來定義一些有特殊用途的類常量,不過這樣定義是存在一些劣勢的。因此const應運而生,之後開發者可以使用const int VAR=100;來定義類常量了。
至於為什麼#define有其劣勢,還要讀者自己去google下。:)
==============================================================================================
情景三:const和指針的配合是噩夢!
你能分辨得清這些聲明麼:
const int *A;
int const *A;
int *const A;
const int *const A;如果有點犯暈的話,那就先給出它們的講解,然後繼續看後面的情景分析吧。
const int *A; //修飾指向的對象,A可變,A指向的對象不可變
int const *A; //修飾指向的對象,A可變,A指向的對象不可變
int *const A; //修飾指針A, A不可變,A指向的對象可變
const int *const A; //指針A和A指向的對象都不可變
==============================================================================================
情景四:const int *A
[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
const int *A=#
printf("result=%d\n",*A);
return 0;
}編譯執行結果為:
[rocrocket@wupengchong const_test]$ cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=12
接下來,我們動動手腳,在代碼中加入了(*A)++;這條語句:
[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
const int *A=#
(*A)++;
printf("result=%d\n",*A);
return 0;
}編譯這個c文件:
[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function ‘main’:
test1.c:6: error: increment of read-only location ‘*A’
可以看到,報錯了,報錯的內容表示”*A”是只讀的,不能修改。
我們再修改一下源代碼為下面這樣:
[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
const int *A=#
A=&tmp;
printf("result=%d\n",*A);
return 0;
}編譯執行結果為:
[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=100
好了,如果你仔細看了這幾個小得不能再小的程序,你自己都可以給出結論了!
結論:如果聲明了const int *A,那麼A值是可以修改的,而*A是不可以修改的。更通俗的說,A指針可以隨便指向一個整型,但只要被A盯上了的整型變量在使用*A引用時就不能修改了。
[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
const int *A=#
A=&tmp;
tmp=3;
printf("result=%d\n",*A);
return 0;
}編譯執行的結果為:
[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=3
結論2:即使A指向了tmp,我雖然不能修改*A,但是我仍然是可以用tmp來修改這個值的,完全不管*A的存在。呵呵www.2cto.com
==============================================================================================
情景五:int *const A
[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int *const A=#
printf("result=%d\n",*A);
return 0;
}編譯執行結果為:
[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=12
我們稍微修改下源代碼:
[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
int *const A=#
A=&tmp;
printf("result=%d\n",*A);
return 0;
}編譯時報錯了:
[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function ‘main’:
test1.c:7: error: assignment of read-only variable ‘A’
[rocrocket@wupengchong const_test]$ cat test1.c
可見A本身的值已經不能再變了。
繼續修改源代碼如下:
[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int *const A=#
(*A)=100;
printf("result=%d\n",*A);
return 0;
}編譯執行結果為:
[rocrocket@wupengchong const_test]$ !cc
cc test1.c
[rocrocket@wupengchong const_test]$ ./a.out
result=100
可以看出,(*A)是可以改變的。
結論又可以輕易推出了:int *const A; //const修飾指針A, A不可變,A指向的對象可變
==============================================================================================
情景六:const int *const A; //指針A和A指向的對象都不可變
[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int const *const A=#
(*A)=100;
printf("result=%d\n",*A);
return 0;
}編譯會報錯:
[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function ‘main’:
test1.c:6: error: assignment of read-only location ‘*A’
改下源代碼:
[rocrocket@wupengchong const_test]$ cat test1.c
#include<stdio.h>
int main()
{
int num=12;
int tmp=100;
int const *const A=#
A=&tmp;
printf("result=%d\n",*A);
return 0;
}編譯仍然會報錯:
[rocrocket@wupengchong const_test]$ !cc
cc test1.c
test1.c: In function ‘main’:
test1.c:7: error: assignment of read-only variable ‘A’
呵呵,結論很明顯了,const int *const A; //指針A和A指向的對象都不可變
當然const int *const A;和int const *const A=#是等價的!
情景七:如果const用在函數形參裡呢?是不是又要復雜很多?
答案是NO!一點也不復雜。
來看看這個函數投:int addnum(const int num, int a, int b);
這個函數聲明中的第一個形參是const int num,這就表明如果我調用了這個函數,那麼第一個實參被傳到addnum函數裡之後,就不能再做修改了!呵呵 就這麼簡單。
給個例子吧,讓大家能更一目了然:
[rocrocket@wupengchong const_test]$ cat test2.c
#include<stdio.h>
int addto(const int num, int a, int b)
{
if(num==1){
return a+b;
}else{
return 0;
}
}
int main(){
int num=100;
int a=12,b=22;
int res;
num=1;
res=addto(num,a,b);
printf("res=%d\n",res);
return 0;
}編譯執行結果為:
[rocrocket@wupengchong const_test]$ !cc
cc test2.c
[rocrocket@wupengchong const_test]$ ./a.out
res=34
如果我修改一下,編譯就會出錯:
[rocrocket@wupengchong const_test]$ cat test2.c
#include<stdio.h>
int addto(const int num, int a, int b)
{
if(num==1){
num=3;
return a+b;
}else{
return 0;
}
}
int main(){
int num=100;
int a=12,b=22;
int res;
num=1;
res=addto(num,a,b);
printf("res=%d\n",res);
return 0;
}編譯報錯為:
[rocrocket@wupengchong const_test]$ !cc
cc test2.c
test2.c: In function ‘addto’:
test2.c:5: error: assignment of read-only location ‘num’
可見在函數裡形參被聲明為const的變量也是不能修改的哦!呵呵~
const其實不難,把本文的幾個小例子看懂就OK了!
除了傳遞要求為const的參數以外,自己聲明對象沒有什麼必須要加,但是對於一個邏輯上不應該被修改,應該為常量的對象,沒有聲明為const,就必須由程序員自己來維護,來記住這個變量不應該被修改,即使你不小心修改導致程序整體混亂了,編譯器也不會報錯
另,const和普通變量的聲明存在於頭文件時有區別,總之這些都是與你具體寫程序的規劃有關系,const這個玩意只是方便程序設計和程序編寫,能夠使程序更加的清晰,如果說我就是不愛用,就是喜歡一路變量用到底,那也沒什麼不行