2008-11-23 73 views
17

我有一個簡單的函數,其中聲明一個數組的大小爲 ,具體取決於int參數。依賴於函數參數的C++數組大小導致編譯錯誤

void f(int n){ 
     char a[n]; 
    }; 

    int main() { 
     return 0; 
    } 

這段代碼編譯罰款GNU C++,但不是MSVC 2005

我得到以下編譯錯誤:

.\main.cpp(4) : error C2057: expected constant expression 
    .\main.cpp(4) : error C2466: cannot allocate an array of constant size 0 
    .\main.cpp(4) : error C2133: 'a' : unknown size 

有什麼事糾正呢?

(我感興趣的是與MSVC這項工作,而無需使用新/刪除)

回答

29

你發現它是Gnu編譯器對C++語言的擴展之一。在這種情況下,Visual C++是完全正確的。 C++中的數組必須定義爲一個編譯時常量表達式的大小。

在1999年的更新中,C語言中增加了一個特性,稱爲變長數組,這是合法的。如果你能找到一個支持C99的C編譯器,這並不容易。但是這個特性不是標準C++的一部分,它不會在C++標準的下一次更新中添加。

在C++中有兩種解決方案。第一種方法是使用一個std :: vector的,第二個就是使用操作new []

char *a = new char [n]; 

當我在寫我的回答,另外一個貼一個建議,使用_alloca。我強烈建議不要這樣做。您只需爲特定於編譯器的交換另一個非標準,不可移植的方法即可。

9

你從堆棧中分配的方法是G ++的擴展。要做到MSVC下的等價,你需要使用_alloca:

char *a = (char *)_alloca(n); 
+0

哦,所以它分配在堆棧上!這真是奇妙:)謝謝! – xxxxxxx 2008-11-23 05:06:40

+1

請注意來自alloca手冊頁的這條評論: BUGS alloca函數依賴於機器和編譯器。在很多系統上,它的實現是很麻煩的。它的使用是不鼓勵的。 – 2008-11-23 06:30:56

+0

是的,但它確實在MSVC下工作,這是OP試圖讓他的代碼工作。多年來我一直在使用它。 – 2008-11-23 18:48:55

2

您可以使用新/刪除堆上分配/釋放內存。這比使用char [n]更慢,可能更容易出錯,但不幸的是,它不是C++標準的一部分。

您可以使用boost的範圍數組類來使用new []的異常安全方法。刪除[]會在a超出範圍時自動調用。

void f(int n) { 
    boost::scoped_array<char> a(new char[n]); 

    /* Code here. */ 
} 

您還可以使用std ::向量,儲備()一些字節:

void f(int n) { 
    std::vector<char> a; 
    a.resize(n); 

    /* Code here. */ 
} 

如果要使用的char [N],編譯爲C99代碼,而不是C++碼。

如果您絕對必須因爲某種原因在堆棧上分配數據,請使用由MSVC庫等提供的擴展_alloca或_malloca/_freea。

5

您正在使用不是標準的東西。其實它是標準C但不是C++。這太奇怪了!

另外解釋一點,運行時大小的堆棧數組不是C++的一部分,而是C99的最新標準的一部分。這就是爲什麼一些編譯器會得到它,而其他編譯器則不會。我建議不要使用它,以避免編譯器兼容性問題。

該功能的替代實現將使用由strager發佈的new和delete。

1

通常在C(除了C99編譯器和其他人指出的那樣)和C++之後,如果你想在堆棧上分配內存,你想要在編譯時知道你想分配的內存大小。局部變量在堆棧中分配,所以在運行時長度取決於函數參數的數組違反了此規則。克萊因是正確地指出,使用new操作符是解決這個問題的一種方法:

 

char *a = new char [n]; 

「A」仍然是在棧上分配的局部變量,但不是被整個數組(具有可變長度),它只是一個指向數組的指針(它總是相同的大小,因此在編譯時已知)。該數組在堆上分配,堆通常用於堆棧的堆棧 - 堆棧用於編譯時已知大小的事物,堆是用於在編譯時不知道大小的事情。

1

使用vector<>而不是數組是否合理?或者,由於您要更換char *,請撥打std::string?這些可以很好地適應運行時大小,但可能有其他原因不能使用它們。

2

可變長度數組在C99中引入。它在gcc中支持,但不支持msvc。據MSVC團隊的一位人士稱,微軟沒有計劃在他們的c/C++編譯器中支持這個功能。他建議在這些情況下使用std :: vector。

請注意,C99不要求在堆棧上分配數組。編譯器可以在堆上分配它。但是,gcc確實在堆棧上分配了數組。

相關問題