標籤:extern c 消失 輸出 array 它的 結果 c++常量 block size
常量摺疊概念
常量摺疊表面上的效果和宏替換是一樣的,只是“效果上是一樣的”,而兩者真正的區別在於,宏是字元常量,在先行編譯宏替換完成後,該宏名字會消失,所有對宏的引用已經全部被替換為它所對應的值,編譯器當然沒有必要維護這個符號,而常量摺疊發生的情況是,對常量的引用情況全部替換為該常量的值,但是,常量名並不會消失,編譯器會把它放入到符號表中,同時會為該變數分配空間,棧空間或全域空間。
void const_test(){ int i0 = 11; const int i=0; //定義常量i int *j = (int *) &i; //看到這裡能對i進行取值,判斷i必然後自己的記憶體空間 *j=1; //對j指向的記憶體進行修改 printf("%d\n%d\n%d\n%d\n",&i,j,i,*j); //觀看實驗效果 const int ck = 9; //這個對照實驗是為了觀察,對常量ck的引用時,會產生的效果 int ik = ck; int i1 = 5; //這個對照實驗是為了區別,對常量和變數的引用有什麼區別 int i2 = i1; }
輸出結果:
0012ff7c
0012ff7c
0
1
(1)ij地址相同,*j==1,而i的值卻實實在在等於0
(2)printf("%d\n%d\n%d\n%d\n",&i,j,i,*j) 別替換為printf("%d\n%d\n%d\n%d\n",&i,j,0,*j)
(3)對可摺疊的常量的引用會被替換為該常量的值,而對變數的引用就需要訪問變數的記憶體
const在集合中的錯誤使用
const可以用於集合,但編譯器不能把一個集合存放在它的符號表裡,所以必須分配記憶體。在這種情況下,const意味著“不能改變的一塊記憶體”。然而其值在編譯時間不能被使用,因為編譯器在編譯時間不需要知道儲存的內容。
const int i[] = {1,2,3,4,5};
int a = i[3];
float f[i[3]]; // illegal
在一個數組定義裡,編譯器必須能產生這樣的移動儲存數組的棧指標代碼,在上面的非法定義裡,編譯器給出的提示是因為它不能再數組定義裡找到一個常量運算式。
const在C和C++中的區別
const int buffsize = 10;char buff[buffsize];
上面的代碼在C++中可以,但在C中不行,因為buffsize佔用儲存的某個地方,所以C編譯器不指定它在編譯時間的值
const int buffsize;
上面的代碼在C中可以,因為在C中預設const為外部連結,C++預設const為內部連結,所以再C++中要寫成extern const int buffsize;
類裡const和enum
在一個類裡,const恢複它在C中的一部分意思,它在每個類對象裡分配儲存並代表一個值,這個值一旦被初始化以後就不能改變。在一個類裡使用const的意思是“在這個對象壽命周期內,這是一個常量”。然而,對這個常量來講,每個不同的對象可以含一個不同的值。所以不能像下面這麼寫:
class bob{ const int nSize = 100; int array[nSize];};
因為在類對象進行了儲存空間分配,編譯器不知道const的內容是什麼,所以不能把它用作編譯期間的常量。
我們可以使用不帶執行個體的無標記的enum
class bob{ enum {nSize = 100}; int array[nSize];};
使用enum是不會佔用對象中的儲存空間的,枚舉常量在編譯時間被全部求值。枚舉在類外面時,佔用4個位元組空間
這樣,在一個類裡建立一個const時,不能給它初值。這個初始化工作必鬚髮生在建構函式裡,並且要在建構函式的某個特殊的地方。因為const必須在建立它的地方被初始化,所有在建構函式的主體裡,const必須已經被初始化,否則就只有等待,直到在建構函式主體以後給它初始化,這樣無法防止在建構函式主體的不同地方改變const的值。
class fred{private: const int nSize;public: fred();};fred::fred():nSize(100){}
C++常量const