2011-06-08 37 views
7

在試圖向某人解釋爲什麼C++靜態數組無法通過動態調整大小時,我發現gcc與我不同意。考慮到argc數組在編譯時不知道,下面的代碼是如何編譯的?C++動態大小的靜態數組益智遊戲

#include <iostream> 
int main(int argc, char* argv[]) { 
    int array[argc]; 
    for(int i = 0; i < argc; i++) array[i] = argv[i][0]; 
    for(int i = 0; i < argc; i++) std::cout << i << ": " << char(array[i]) << std::endl; 
    //for(int i = 0; i < 100; i++) { std::cout << i << " "; std::cout.flush(); array[i] = 0; } 
    return 0; 
} 

我用gcc 4.2.1測試了這個,並且指定了-Wall,沒有從編譯器中弄髒髒的樣子。如果我取消註釋最後一個循環,則當我將其分配給數組[53]時,會發生段錯誤。

我以前放置防護件陣列之前和陣列的聲明之後,並已以零填充它們,可以肯定,該程序必須被搗毀其堆棧的一部分,但GCC重新排序堆棧上的變量,使得我無法觀察到任何數據損壞。

很顯然,我並不想讓這段代碼「工作」。我只是想了解爲什麼gcc甚至認爲它可以編譯代碼。任何提示或解釋將不勝感激。

更新:感謝所有您的幫助和可笑的快速響應!

+0

由C99讓我覺得:http://bytes.com/topic/c/answers/770297-c99-dynamic-array – Kevin 2011-06-08 19:59:56

+3

另一個基本問題是你正在使用一個編譯器來測試語言中是否有可能。你可以在gcc中指定一個標準,並且你可以要求嚴格遵守標準('-pedantic'?),但你沒有,因此你允許編譯器擴展。 – 2011-06-08 20:01:25

回答

3

這些被稱爲可變長度數組(自C99開始可用),可以僅聲明爲自動變量 - 嘗試將static放在前面,編譯器將拒絕它。它只涉及用一個變量而不是一個常量偏移量增加堆棧指針,不超過這個。

在引入可變長度數組之前,使用alloca函數在堆棧上分配可變大小的對象。

2

可變大小的基於堆棧的數組是G ++的擴展,在那裏完全合法。但是,它們不是標準的。基於堆棧的數組的確可以在大多數實現上進行可變大小的調整,但標準並沒有強制要求這樣做。

2

除非使用常量表達式,否則不能調整C++中的數組大小。通過一個非常量大小的數組是C99的一部分,或者是GCC強加給我們的一個可怕的擴展。編譯C++代碼時,可以使用-pedantic標誌來擺脫大部分GCC垃圾。

+0

你爲什麼認爲這是一個可怕的特點?它允許您通過分配儘可能多的空間來更有效地使用可用的堆棧空間。 – 2011-06-08 20:12:59

+0

@Blagovest嗯,你的意思是使用普通的基於棧的數組呢?這是廢話,C社區中的許多人(以及C++社區中的每個人都這樣認爲)。此外,它將永遠不會成爲C++的一部分,所以這是一個可移植性問題。 – 2011-06-08 20:30:10

6

這是一個Variable Length Array,它是C99標準的一部分。但它不是C++的一部分。

您也可以使用alloca功能,這也不是標準C++,但廣泛的支持:

int main(int argc, char* argv[]) 
{ 
    int* array = (int*) alloca(argc * sizeof(int)); 
    array[0] = 123; 
    // array automatically deallocated here. Don't call free(array)! 
}