2014-07-25 81 views
3

,不知是否安全根據C99的標準,來解釋這樣一個結構:類型雙關語:INT []和struct {INT ...}

struct my_struct_t { 
    int a; 
    int b; 
    int c; 
}; 

作爲int[3]。即這個代碼片段是否適合所有ABI?

struct my_struct_t f; 
int *i = &f.a; 
i[0] = 1; // f.a == 1 
i[1] = 2; // f.b == 2 
i[2] = 3; // f.c == 3 

據我理解標準,編譯器允許在結構成員之後添加填料,但不能是陣列內部的任何填充。我是否正確? (如果我是,那麼代碼示例將產生不確定的行爲。)

+2

這是官方不安全的,但可能會在任何理智的實現上工作,因爲沒有理由對結構中的int數組和int字段有不同的填充規則。 –

回答

3

唯一真正的「答案」,這是一個引文:

C11,6.7.2.1:

可能有結構對象內的未命名填充,但不在其開始處。 (第15段)
在結構或聯合的末尾可能有未命名的填充。 (第17段)

C11,6.2.5:

數組類型描述了一種連續地分配非空集合與特定的成員對象類型的對象(第20段)

由於下標運算符與指針算術運算完全等價,它不能考慮任何可能存在的填充(無論如何)(在目標對象的類型外部),並且可能存在於結構中。

+0

謝謝!你的報價正是我一直在尋找的! – kay

+1

@Kay基本書籤材料:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf – Leushenko

3

由於int s是,很好,int -aligned,我認爲它應該在大多數平臺上工作(它在我的英特爾x86-64與gcc在Linux上)。

您可以檢查它是否工作在編譯時:

static_assert(offsetof(struct my_struct_t, c) == 2*sizeof(int)); 

當且僅當這一說法並沒有失敗,該標準保證你是安全的(如果我沒有錯得要命,但我可以」沒有想到任何使它成爲UB的東西)。

+0

+1,靜態斷言會發現錯誤。 (我主要關心模糊,廉價的嵌入式系統。:-) – kay

+0

**注意**我重新考慮了這個問題,現在我想(假設靜態斷言成功),它與「struct hack」一樣多。哪個IMO符合要求,但許多人不同意(包括標準委員會),儘管沒有合格的實施證明我錯了。 – mafso