2011-04-20 62 views
4

我不是一個C++專家,但據我所知,這個碼應該會由於size不固定:什麼時候變長數組合法?

#include<iostream> 

using namespace std; 

int main(int argc, char** argv) 
{ 
    int size = *argv[1] - 48; 
    char array [size]; 
    cout<<sizeof(array)<<endl; 

    return 0; 
} 

爲什麼這個工作時,我編譯與海灣合作委員會(最好說G ++)?

./test 7 
7 
/test 2 
2 

回答

1

這是一個C99功能,允許您在堆棧中聲明類似的數組。

2

這是一個非標準的GCC擴展 - 其他編譯器如Visual C++不支持。

0

即使沒有VLA擴展,代碼也可以在編譯器未能推導出維度表達式在編譯時不爲人知的情況下進行編譯。它仍然是UB。

0

因爲您沒有將g ++作爲C++編譯器調用。如果我嘗試它,我會收到警告,明確指出「ISO C++禁止可變長度數組」。但是我的makefile包括選項-std=c++98,至少當我想編譯可移植的C++時。

3

這是一個list of new features in C99其中增加了variable length arrays

另見$ 6.7.6.2/4 數組聲明N1548ISO/IEC 9899:201X委員會草案 - 2010年12月2日N1548),詳細了。

+1

*但*:沒有C++標準曾接受過C99的VLA,因此從技術上講,在C++中接納VLA的事實是'g ++'擴展。 – 2012-07-28 01:45:31

5

要從堆棧或堆中爲變量分配內存,變量的大小需要知道。 C++編譯器可以自己決定如何分配內存,但是C++已經公開了他們希望C++編譯器如何處理這種情況,因此C++ std要求編譯器供應商發佈他們的內存處理。這是通過sizeof運算符發生的。該運算符在編譯時完全計算。數組大小的編譯時間限制來自此要求。

int arr[10]; 
std::cout << sizeof(arr) << std::endl 

因爲每個變量和類型都支持sizeof,所以它們的大小需要在編譯時在C++中計算。因此,變長數組在C++中是不可能的。

這個要求還有另一個非常重要的限制。原則上,C++編譯器供應商可以計算C++程序堆棧所需的最大內存量(如果沒有問題的話):對於遞歸函數,不能計算程序使用的堆棧大小,但對於其他任何情況,堆棧大小都可以通過執行以下操作來計算:

  1. 使用sizeof(a)用於在堆棧幀
  2. 總和的每個變量的變量的尺寸,以獲取該堆棧幀
  3. 列表中的所有可能的堆棧所需的存儲器量幀並計算其大小
  4. 挑選最大尺寸的調用堆棧
  5. 選擇該大小作爲程序堆棧的大小。

不幸的是,遞歸函數打破了整個方案。而且它需要全局程序的流程分析來重新識別哪些函數可能具有無限的調用堆棧。但是編譯時sizeof運算符的限制很重要,否則我們的C++程序會隨機用盡堆棧空間,導致崩潰和不穩定。這是不可接受的。因此每個變量和類型都支持編譯時sizeof運算符。

VLA支持要求編譯器可以生成代碼,其中通常生成的偏移量作爲結果機器代碼的常量在運行時實際上是可修改的。符合標準的C++編譯器通常無法做到這一點。 C決定添加這個支持,因此C編譯器可以做到這一點。但在這個過程中,他們需要打破運營商規模。編譯時不再可以計算大小。如在C標準中規定的VLA的支持有很大的問題:

  1. 你不能把VLA結構或類中
  2. VLA的基本上僅限於本地函數範圍

這些問題已經解決在C++中通過std :: vector沒有任何這些問題。

1

c99支持可變長度數組(VLA),但既不c90也不C++支持可變長度數組,但是gcc支持此作爲an extension in both C and C++你可以看到這更清楚地,如果你有這些參數編譯:

gcc -std=c89 -pedantic 

這將給你以下警告:

warning: ISO C90 forbids variable length array ‘array’ [-Wvla] 

g++

g++ -pedantic 

會給你這樣的警告:

warning: ISO C++ forbids variable length array ‘array’ [-Wvla] 

gcc手冊此standards節進入更多的細節。重要的是要注意,截至2011年C標準可變長度陣列(VLA)現在是可選的。