簡體   English   中英

在C中聲明具有可變大小的全局結構變量

[英]Declare Global Struct Variable With Variable Size In C

我有一個看起來像這樣的結構。

struct MyStruct1 {
    int (*fn)();
    int b;
}

另一個看起來像這樣的結構。

struct MyStruct2 {
    int a;
    struct MyStruct1 b[0];
}

我想聲明一個MyStruct2類型的全局變量,有點像這樣。

int func1() { return 1; }
int func2() { return 2; }
struct MyStruct2 a = { 1, { func1, 5 }, { func2, 6 } };

但是,我得到一個“初始化器元素不是編譯時常量”。

我想知道(a)是否有可能全局聲明一個可變大小的結構(或至少定義一個大小正確的空間塊,以便稍后再插入值),以及(b)是否是,我在做什么錯?

您不能合法地在C中創建大小為0的數組。 在C99或C11中,您可以使用“彈性數組成員”,如下所示:

struct MyStruct2 {
    int a;
    struct MyStruct1 b[];
};

但是只有通過動態內存分配才能有效地創建具有靈活數組成員的結構(其他形式的分配會給您一個大小為0的不可用的靈活數組)。

具有可變大小數組的結構的較舊“結構破解”版本在結構中使用大小為1的數組。 您可以使用大小為1的數組創建此類結構的全局版本。

但基本上,您正在嘗試執行該語言禁止您執行的操作,並且並不奇怪,您正在失敗。

您如何處理取決於您的需求。 全局變量從本質上來說是不希望有的,因此有一個元素“您應該嘗試避免這樣做”。 也就是說,規則也適用於文件范圍( static )變量,並且具有許多用途。

您可以使用顯式指針代替數組,並對struct MyStruct2的主體及其struct MyStruct1成員的數組進行單獨分配。 您可以放棄全局變量,並通過靈活的數組成員使用動態分配的結構。

struct MyStruct2 *ms2 = malloc(sizeof(*ms2) + N * sizeof(ms2->b[0]));

這將創建一個具有數組中N成員的struct MyStruct2 (如該答案的頂部所示)。 無需進行任何進一步的更改,就可以使用ms2->b[0]ms2->b[N-1] (好,除了錯誤檢查malloc()成功外)。

不可能在本地或全局聲明可變大小的struct 每種類型在編譯時都具有固定的大小。

但是,您報告的錯誤消息令人驚訝。 如果您給出的所有聲明都位於文件范圍內,並且按照給定的順序位於同一文件中,則變量a的初始化程序一個編譯時常量。 但是,它不是struct MyStruct2的適當初始化struct MyStruct2

  • 因為它指定的元素多於該struct類型具有的成員,
  • 因為ab的初始值設定項元素是struct MyStruct1的初始值struct MyStruct1而不是此類數組的初始值struct MyStruct1
  • 因為即使將最后兩個初始值設定項元素轉換為一個數組初始值設定項,也要擁有比ab中的元素更多的元素(即大於零)。

如果您想要一個動態大小的數組,無論是作為變量本身還是作為struct的成員,則必須聲明一個指向它的指針,並為元素動態分配內存。 在這種情況下,元素本身不是struct一部分; 只有指向它們的指針。 (順便說一下,這與大小固定在其初始值設定項中的固定大小的數組不同;但這僅適用於獨立類型,而不適用於structunion成員的類型)。

編輯:正如ShafikYaghmour所說,C99靈活數組是一種可能的選擇。 它們與作為動態分配數組指針的struct元素相似但不相同。 但是,在那種情況下,您不僅不能靜態聲明數組元素,還不能靜態聲明該struct本身的實例,因此這根本不會解決初始化程序問題。 還有其他一些怪癖和局限性。 就我個人而言,我沒有看到靈活數組的優點,但是它們確實使正確釋放結構實例變得容易一些。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM