偶然在CSDN的論壇上看到這樣的題目,代碼如下:
const int a=3;
int *p=(int*)&a;
*p=100;
printf("*p =%d,a = %d\n",*p,a);
printf("p = %p,a = %p\n",p,&a);
程序中p和a的地址一樣,可值不一樣,容易讓人產生錯覺。有人說這樣做改變了常量a的值,調試跟蹤中發現a的值是100,可輸出的卻是3;還有人認為是常量折疊的緣故。其實這兩種說法都是錯誤的,沒抓住問題的本質。在這個程序中,通過int *p=(int*)&a;這個語句,常量a和指針p的地址是一樣的,但是由于它們所屬的內存區的不同,在棧區我們看到*p值是100,常量區的值是3.
在C++中,常量確實不分配內存,但是當對常量取地址時就已經分配了空間,常量是不可以改變的,但我們要記住的是:常量和常量的地址是兩個概念,常量不可以改變,但是常量的地址可以改變,所以說,改變了常量a的值,說法是不正確的;至于在調試中,發現a的值是100(VC編譯器的調試模式下的觀察窗口下,用鼠標點到a的地址處),可輸出的是3,那是因為,常量a和變量p是一個地址,但是卻分屬不同的內存區域,a是常量區,p是棧區,我們觀察的地址在棧中,所以看到的值是100(其實是存儲在指針p指向的地址中的值100),可輸出a的值3,a的值并沒變;這里和常量折疊的關系不大,至少不是它的實質,如果把const去掉值就一樣了。
值得注意是:這樣的代碼容易讓人產生錯覺,如果再有內存分配的話,很容易出問題,并不提倡這樣的代碼。一直一來認為,C++很大,注重的是細節,這里再次驗證了這一點。