簡體   English   中英

在使用靈活數組的結構初始化中使用sizeof運算符

[英]Using the sizeof operator in the initialization of a struct with a flexible array

我想在其中聲明一個具有靈活數組成員的結構,然后在其上使用sizeof() 原型是:

typedef struct
{
    uint16_t    length;
    uint8_t     array[][2];
} FLEXIBLE_t;

然后,我聲明:

const FLEXIBLE_t test = {
    .length = sizeof(test),
    .array = {  {   0,  1   },
                {   2,  3   },
                {   4,  5   },
                {   6,  7   },
                {   8,  9   } }
};

一切都可以編譯(GCC),但是當我檢查test.length它的值為2,即,它僅將uint16_t用作length本身。

如何在編譯時計算結構的大小? 似乎編譯器使用原型而不是特定實例。

sizeof忽略了柔性數組成員,因為柔性數組成員在結構內不占用空間。

C11-§6.7.2.2/ 18

作為一種特殊情況,具有多個命名成員的結構的最后一個元素可能具有不完整的數組類型; 這稱為靈活數組成員。 在大多數情況下,柔性數組成員將被忽略。 特別地,該結構的尺寸就好像省略了柔性陣列構件,除了其可能具有比省略所暗示的更多的尾隨填充。 [...]

請注意,標准C不允許像代碼中那樣初始化靈活數組成員。 它將調用未定義的行為(請參見第6.7.2.2節第20和21段)。 雖然GCC允許將此作為擴展

GCC允許對靈活數組成員進行靜態初始化 這等效於定義一個包含原始結構的新結構,后跟一個足夠大的數組來容納數據。

靈活的數組成員不計入大小:

……特別是,該結構的尺寸就好像省略了柔性陣列構件,只是它的尾隨填充物可能比省略所暗示的要多。

除了大小問題之外,您的代碼在C中還具有未定義的行為。不能像這樣初始化靈活的數組成員。 在這種意義上,Gcc可能具有擴展名,但這不是可移植的。

GCC允許初始化靈活數組作為擴展: https : //gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/Zero-Length.html

但是,sizeof()遵循C標准,並認為結構中的靈活數組的大小為零。 無論如何,當嘗試在該結構的初始化程序中使用sizeof()時,該結構在該階段是不完整的,最終大小尚不清楚。 只有原型的大小及其零長度的靈活數組是已知的。

但是,大小在編譯時就知道了,直到結構初始化之后才知道。 在這種情況下,GCC的__builtin_object_size()將求值為數字常量,但必須從函數中調用它,因為它並不總是常量,因此不能在初始化程序中使用。

因此,必須在運行時分配.length ,但是至少要分配的值可以編譯為常數:

test.length = __builtin_object_size(test, 0);

sizeof()運算符返回的sizeof() (幾乎)忽略了靈活數組。

根據C標准6.7.2.1結構和聯合說明符第18段

作為一種特殊情況,具有多個命名成員的結構的最后一個元素可能具有不完整的數組類型; 這稱為彈性數組成員。 在大多數情況下,柔性數組成員將被忽略。 特別地,該結構的尺寸就好像省略了柔性陣列構件,除了其可能具有比省略所暗示的更多的尾隨填充。

暫無
暫無

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

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