簡體   English   中英

為什么當n是const值時int x [n]是錯誤的?

[英]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關鍵字的真正含義是“只讀”。 常數是數字文字,例如421.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[n]是錯在何處n是一個const的值?

n不是常數。 const僅保證n是一個“只讀”變量,在程序執行期間不應對其進行修改。
請注意,在 ,與不同, const限定變量不是常量。 因此,聲明的數組是可變長度數組。
您不能使用初始化列表來初始化可變長度數組。

C11-§6.7.9/ 3:

要初始化的實體的類型應為未知大小的數組或不是可變長度數組類型的完整對象類型

您可以使用#defineenum來使n為常數

#define n 5
int x[n] = { 1,1,3,4,5 };   

如果您要窮舉初始化數組,那么讓編譯器推斷數組大小會更加容易,安全和可維護:

int x[] = { 1,1,3,4,5 };
const int n = sizeof(x) / sizeof(*x) ; 

然后,要更改數組大小,只需更改初始化程序的數量,而不必更改大小初始化程序列表以匹配。 當有許多初始化程序時特別有用。

即使nconst ,也不能使用它來定義數組的大小,除非您希望創建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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM