2012-12-28 56 views
7

可能重複:
Variably modified array at file scope可變長度陣列(VLA)在C和C++

我對VLA和它的行爲,我需要澄清的一些概念。

AFIK因爲C99有可能VLA申報到本地範圍:

int main(int argc, char **argv) 
{ 
    // function 'main' scope 
    int size = 100; 
    int array[size]; 
    return 0; 
} 

但它在全球範圍禁止:

const int global_size = 100; 
int global_array[global_size]; // forbidden in C99, allowed in C++ 

int main(int argc, char **argv) 
{ 
    int local_size = 100; 
    int local_array[local_size]; 
    return 0; 
} 

上面的代碼聲明瞭一個VLA在C99因爲const修改不會創建編譯時值。在C++ global_size中是編譯時的值,所以global_array不會變成VLA。

我需要知道的是:我的推理是否正確?我所描述的行爲是正確的?

我也想知道:爲什麼全球範圍內的VLA是不允許的?在C和C++中都被禁止?數組在全局和局部範圍內行爲的原因有什麼不同?

+5

讓我們假設全球的VLA是允許的。他們的(可變)大小何時實際定義? – cnicutar

+0

@cnicutar ......就像所有的VLA一樣,在執行時間裏,就像其他的範圍一樣。我知道這不是答案,但我想知道爲什麼。 –

+1

http://stackoverflow.com/a/5052083/174605 – coelhudo

回答

5

是的,你的推理是正確的,那就是C和C++如何看待這些不同形式的數組聲明和定義。如其他人已經指出的那樣,在全球範圍內具有可變長度(非const)的VLA很難理解。評估順序是什麼,例如,如果長度表達式指的是不同編譯單元的對象? C++沒有VLA,但它具有在文件範圍內對象的動態初始化。如果你不得不依賴評估順序,這已經讓你頭疼不已。

這爲C語言留下了一個小小的空白,其中包含一個不允許的合格對象const的長度表達式。這源於這樣的事實,即這些對象不被C標準認爲是「整數常量表達式」。這在未來的版本中可能會改變,但到目前爲止,C委員會並沒有發現有必要允許這樣的事情:在C中扮演這個角色的常量有enum。他們唯一的限制是它們僅限於int C,如果也有他們,size_t

+0

終於有人證明已經讀完整個問題! (+1爲此)恕我直言,這個問題不是[重複](http://stackoverflow.com/questions/1712592/variably-modified-array-at-file-scope),因爲我專注於其他事實。感謝您解答並感謝您回答幾乎所有的問題。 –

1

被禁止和不被允許有區別。 ;-)

VLA功能旨在允許使用本地數組的堆棧空間,以避免使用malloc進行堆分配。這主要是速度優化。

現在你想在功能之外使用VLA。爲什麼?在程序啓動過程中避免單個malloc調用沒有太多的優勢。我們應該使用什麼棧空間來處理靜態生命週期的變量?

3

我認爲根本的原因是一個全局變量有聯繫,它的大小必須在編譯時知道。如果不是,那麼如何鏈接該程序?

局部變量沒有鏈接,並且VLA在堆棧上分配,隨着程序運行,它會動態增長。

2

C++不支持VLA,句點。第二個代碼片段在C++中工作的原因是const關鍵字在C++中創建編譯時常量;在C中,它不是。

無論您聲明大小變量的方式如何,C99都不支持塊範圍外的VLA。請注意,C2011使VLA支持可選。

+0

是的,我知道'const'關鍵字在C++中創建一個編譯時常量,而在C中它不會,我在這個問題上評論過這個。 –

1

因此,對於全球VLA的,的問題(也有在主題很多變種),可以在這裏顯示:

int size; 
int a; 
int v[size]; 
int b; 

.... 在另一個文件:

extern int a; 
extern int b; 

鏈接器必須知道鏈接時彼此之間的關係,否則它將無法在加載時正確地修復它們。