![](/img/trans.png)
[英]How does `int sum = n + - + - + - + n` compile where `n` is an `int`?
[英]Why is int x[n] wrong where n is a const value?
我不明白為什么這樣做是錯誤的:
const int n = 5;
int x[n] = { 1,1,3,4,5 };
即使n
已經是一個const值。
雖然這樣做似乎適合GNU編譯器:
const int n = 5;
int x[n]; /*without initialization*/
我知道C99的VLA功能,並且我認為它與正在發生的事情有關,但是我只需要對后台發生的事情進行一些說明即可。
要記住的關鍵是const
和“ constant”是兩個完全不同的東西。
const
關鍵字的真正含義是“只讀”。 常數是數字文字,例如42
或1.5
(或枚舉或字符常數)。 常量表達式是可以在編譯時求值的一種特殊類型的表達式,例如2 + 2
。
因此給出一個聲明:
const int n = 5;
表達式n
引用對象的值,並且不將其視為常量表達式。 典型的編譯器會優化對n
的引用,將其替換為用於文字5
的相同代碼,但這不是必需的-表達式是否為常數的規則由語言而不是由的聰明決定。當前的編譯器。
const
(只讀)和constant (在編譯時求值)之間的差異的一個示例是:
const size_t now = time(NULL);
const
關鍵字表示您不允許在初始化后立即修改now
的值,但顯然要在運行時間之前才能計算time(NULL)
的值。
所以這:
const int n = 5;
int x[n];
在C中比沒有const
關鍵字更有效。
該語言可以 (並且恕我直言,可能應該)將n
評估為常量表達式; 只是沒有這樣定義。 (C ++確實有這樣的規則;有關血腥細節,請參見C ++標准或不錯的參考。)
如果要使用值為5
的命名常量,最常見的方法是定義一個宏:
#define N 5
int x[N];
另一種方法是定義一個枚舉常量:
enum { n = 5 };
int x[n];
枚舉常量是常量表達式,並且始終為int
類型(這意味着此方法不適用於int
以外的類型)。 可以說這是對enum
機制的濫用。
從1999年的標准開始,可以定義一個非恆定大小的數組。 這是一個VLA或可變長度數組。 此類數組僅在塊范圍內被允許,並且可能沒有初始化程序(因為編譯器無法檢查初始化程序具有正確數量的元素)。
但鑒於您的原始代碼:
const int n = 5;
int x[n] = { 1,1,3,4,5 };
您可以讓編譯器從初始化程序推斷長度:
int x[] = { 1,1,3,4,5 };
然后,您可以根據數組的大小計算長度:
const int x_len = sizeof x / sizeof x[0];
如果您要窮舉初始化數組,那么讓編譯器推斷數組大小會更加容易,安全和可維護:
int x[] = { 1,1,3,4,5 };
const int n = sizeof(x) / sizeof(*x) ;
然后,要更改數組大小,只需更改初始化程序的數量,而不必更改大小和初始化程序列表以匹配。 當有許多初始化程序時特別有用。
即使n
是const
,也不能使用它來定義數組的大小,除非您希望創建VLA。 但是,您不能使用初始化程序列表來初始化VLA。
使用宏來創建固定大小的數組。
#define ARRAY_SIZE 5
int x[ARRAY_SIZE] = { 1,1,3,4,5 };
您的代碼與myfunc()
在語義上是否不同:
void myfunc(const int n) {
int x[n] = { 1,1,3,4,5 };
printf("%d\n", x[n-1]);
*( (int *) &n) = 17; // Somewhat less "constant" than hoped...
return ;
}
int main(){
myfunc(4);
myfunc(5);
myfunc(6); // Haven't actually tested this. Boom? Maybe just printf(noise)?
return 0;
}
n
是否真的一直不變? 您認為編譯器應該為x[]
分配多少空間(因為這樣做是編譯器的工作)?
正如其他人所指出的那樣,CV-預選賽const
並不意味着“在編譯期間和之后所有的時間是恆定的值”。 它的意思是“本地代碼不應更改(盡管可以更改)的值”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.