2010-04-26 65 views
7

對於下面的C++代碼段:用未指定大小定義的靜態數組,空括號?

class Foo { 
    int a[]; // no error 
}; 

int a[];  // error: storage size of 'a' isn't known 

void bar() { 
    int a[]; // error: storage size of 'a' isn't known 
} 

爲什麼不成員變量引起的錯誤太?這個成員變量的含義是什麼?

我使用gcc版本3.4.5(mingw-vista特別)通過CodeBlocks 8.02。

在Visual Studio速成2008 - 微軟(R)C/C++優化編譯器15.00.30729.01爲80×86,我得到了以下信息:

class Foo { 
    int a[]; // warning C4200: nonstandard extension used : zero-sized array in struct/union - Cannot generate copy-ctor or copy-assignment operator when UDT contains a zero-sized array 
}; 

int a[]; 

void bar() { 
    int a[]; // error C2133: 'a' : unknown size 
} 

現在,這需要一定的交代了。

+0

標題提到「靜態數組」。這些「靜態數組」在你的問題在哪裏?我沒有看到任何「靜態數組」的引用。 – AnT 2010-04-27 00:11:18

+0

我的意思是靜態分配數組。如果您認爲有必要,請隨時編輯該問題。謝謝。 – 2010-05-01 09:01:48

回答

6

C99支持所謂的「靈活」數組成員,它被允許成爲結構的最後一個成員。當您動態分配這樣一個結構時,您可以增加從malloc()請求的數量以爲該陣列提供內存。

一些編譯器將此作爲C90和/或C++的擴展。

所以,你可以有這樣的代碼如下:

struct foo_t { 
    int x; 
    char buf[]; 
}; 


void use_foo(size_t bufSize) 
{ 
    struct foo_t* p = malloc(sizeof(struct foo_t) + bufSize); 

    int i; 

    for (i = 0; i < bufSize; ++i) { 
     p->buf[i] = i; 
    } 
} 

不能直接與靈活的數組成員定義結構(作爲本地或全局/靜態變量),因爲編譯器不會知道爲它分配多少內存。

我真的不知道你怎麼會輕易使用這樣的事情與C++的new運營商 - 我想你可以分配內存使用malloc()和使用位置new的對象。也許可以使用operator new的某些類/結構特定的過載...

2
class Foo { 
    int a[]; // OK in C, invalid in C++. Does not work with inheritance. 
}; // Idea is that structure is "extended" indefinitely by an array. 
    // May work on your compiler as an extra feature. 

int a[];  // error in C and C++: storage size of 'a' isn't known 

void bar() { 
    int a[]; // error in C and C++: storage size of 'a' isn't known 
} 

extern int a[]; // OK: storage size may be declared later. 

int a[5]; // declaration of size before use. 

未指定大小的數組類型不完整。 8.3.4/1:

如果省略了常量表達式,d的標識符的類型是「結合的T未知的派生聲明符類型列表陣列」,一個不完整的對象類型。

它必須完成才能參與定義,即a的定義必須包含大小規範或具有指定大小的數組的初始化。

+1

我不明白「使用前必須完成」的評論。 *在C++中使用*未指定大小的數組是完全合法的。你不能將'sizeof'應用於它,但你可以合法地訪問它的元素。 – AnT 2010-04-27 00:09:17

+0

@Andrey:聲明爲未指定大小的數組的函數參數的類型爲'T *'。這是另一種類型的衰變。我應該注意到另一個例子嗎?你的答案似乎沒有顯示任何。 – Potatoswatter 2010-04-27 02:48:00

+0

我不是在談論函數參數,這是一個完全不同的故事。我在你的例子中引用了'extern int a []'聲明。一旦你聲明瞭這樣一個數組,你可以*使用*它已經。我看到你刪除了對「使用」的引用。 – AnT 2010-04-27 03:17:08

0

我們用它來表示某種可變長度的記錄。就像頭文件一樣,該文件具有關於要遵循多少結構的信息,其次是數據本身。它是一個可變長度的數組,我發現它在編譯器之間不太受支持。有些想要array [];有些想要array [0]; (老式)。

11

C++語言允許僅在非限定聲明省略數組大小

extern int a[]; // non-defining declaration - OK in C++ 

int a[]; // definition - ERROR in C++ 

int a[5]; // definition - OK, size specified explicitly 
int a[] = { 1, 2, 3 }; // definition - OK, size specified implicitly 

非靜態類成員decarations總是需要指定數組大小

struct S { 
    int a[]; // ERROR in C++ 
}; 

而靜態類成員decarations可省略大小

struct S { 
    static int a[]; // OK in C++ 
}; 

(同一成員的定義當然必須指定大小)。

任何與此行爲的偏差只能通過編譯器的擴展非標準行爲來解釋。也許你應該指定一些額外的編譯器設置,使其表現更迂迴。