2009-11-02 75 views
4

我有一種情況,我希望我的程序能夠讀取一些數字來定義二維數組的大小(用作矩陣)。我原本認爲,要做到這一點的唯一方法是使用一個malloc調用把陣列上堆,是這樣的:可以使用一個變量來定義棧中數組的大小c?

matrixElement* matrix = malloc(sizeof(matrixElement) * numRows * numCols); 

其中數numCols和numRows行爲進行了早期閱讀的整數, matrixElement是一些任意類型。我的理由是,簡單地寫:

matrixElement matrix[numRows][numCols]; 

是行不通的,因爲編譯器將無法知道多少堆棧空間分配給函數調用的方式。事實證明,我錯了,因爲下面的代碼編譯和運行:

#include <stdio.h> 
#include <stdlib.h> 

int main(void) 
{ 
    int x, y; 
    scanf("%d", &x); 
    scanf("%d", &y); 

    double arr[x][y]; 

    printf("Made an array of size %d by %d, total memory %fKb\n", 
      sizeof(arr)/sizeof(arr[0]), 
      sizeof(arr[0])/sizeof(arr[0][0]), 
      (float) sizeof(arr)/1024.0f); 

    return 0; 
} 

有了很大的輸入x和y的足夠多,這最終會給出一個段錯誤,但我也希望看到,我可以創造非常驚訝帶有此代碼的1000x1000陣列。

任何人都可以解釋這裏發生了什麼?

是編譯器只是分配一堆空間爲陣,即使它不知道有多少會用嗎?

是由ANSI C指定此行爲或只是一些海灣合作委員會在其自身在做什麼?

回答

8

此功能在C99中添加。該數組在堆棧上分配的方式類似於您撥打alloca()時的方式。可能有一些細微的差異;檢查您的編譯器文檔的信息。

GCC documentation對其實現進行了說明。

+2

但請注意,對此的支持很不明顯。即使在GCC試圖支持它一段時間,它顯然是甚至到4.3版本(http://gcc.gnu.org/gcc-4.3/c99status.html) – 2009-11-02 19:06:21

+0

+1,是絕對正確的。這可能是C99中最有爭議的一個。 – 2009-11-02 19:07:01

+2

請注意,你的堆棧通常比你的堆小得多。如果你想動態調整任何實際大小的數組,使用malloc()可能是一個好主意。還要記住,像所有本地(非靜態)對象一樣,這些數組一旦你的函數返回就會消失。 – 2009-11-02 19:15:43

3

C99添加了對變長數組(有時稱爲「VLA」)的支持。許多C編譯器在C99之前也支持這一點。許多人也支持「分配」功能,即使做了同樣的事情,但方式稍微不方便。

典型實現分配「正確」的空間量。從本質上講,堆棧指針只是根據可變長度數組的大小進行調整。爲了確保堆棧指針在返回時被「彈出」正確的數量並且放置在堆棧上的自動變量以正確的偏移量被訪問,需要做一些額外的簿記工作。

3

您應該對此感到驚訝,因爲您可以在塊的中間聲明您的arr數組,因爲您對其可變指定大小感到驚訝。兩者都是C99語言規範的新功能。作爲C89/90的延伸,GCC編譯器都支持它們一段時間。但在「經典」ANSI C即C89/90中都不合法。

如果要編譯在C89/90模式的代碼(這是默認GCC),那麼你確實處理GCC的東西是做根據自身。如果您使用-std=c99模式編譯代碼,那麼您正在處理[相對]新的標準語言功能。

+1

除了'任何地方的聲明'更常被看作C90和C++代碼的擴展,而VLA並不常見。 – 2009-11-02 19:57:00

相關問題