2013-07-22 58 views
4

any_t是任何類型(intstruct something,...)。C結構:沒有填充的連續字段?

考慮這樣的結構:

struct my_struct { 
    any_t val, 
    any_t array[10] 
} 

如果我定義一個變量v

struct my_struct v; 

是可以安全使用&v.val爲11個any_t項的數組?

any_t *p = &v.val; 
f(p[0]); 
f(p[5]); 
f(p[10]); 

它是保證沒有填充將valarray之間增加?

+3

你可以使用#pragma pack(1)來保證成員之間沒有空格 – Kevin

+0

http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the值得閱讀的每個成員的大小的總和。 – yeyo

回答

7

單從C標準,它不是安全使用&v.val作爲11 any_t這些原因的數組:

  • C標準允許無名內部填充在一個結構:C 2011(N1570)6.7 .2.1 15,「有可能是一個結構對象中的無名填充,但不是在它的開始。」這將是不尋常的C實現插入valarray之間的填充,因爲對齊要求將不需要它,但它是允許的並且在某些情況下可以想象得到有益的結果,例如使array更好地對準性能(而不是必需)。
  • 即使保證valarray元素的間距與11 any_t的數組相同,也不能保證指針運算能夠正常工作。 Ç2011(N1570)6.5.6 8限定指針算法(包括數組索引),並且只需要一個陣列內算術工作(包括在最後一個名義元素)。一些C實現使用基址和偏移量尋址。在這種情況下,val的基地址可能無法支持延伸到array的偏移量。
  • 即使是C實現使用正常處理,其優化允許使基於C++的標準扣除額。理論上,優化器可以看到一個指針來自val的地址,因此不能(按照C標準)用於尋址array中的任何東西。例如,如果你做了any_t *p = &v.val; p[i] = 3; v.array[j] = 4;,優化程序可能會將作業分配爲v.array[j]p[i]作爲獨立對象,並以任意順序執行它們,即使您可能已設置ij以便它們指向相同的元素。
+0

很清楚,謝謝! – rom1v

+0

這個標準似乎有點模糊不清,關於指針的實現可能或不能合法地做什麼,指針超出了數組的聲明大小;因爲我還沒有意識到任何證明或者反對「傳統」版本的「struct hack」(使用第一個數組)的東西。然而,關於你的後一點,我認爲如果一個結構在malloc的空間內,將一個元素的地址賦給一個void *然後返回到它的元素類型應該保證事情應該能夠工作實際上位於正確的地方。 – supercat

+0

除非指定了特定的實現,否則我不認爲有任何可移植的方式來使用array-ish訪問結構成員,除非已經定義了一個明確列出的結構成員的偏移數組(除其他外,不能保證成員將被等間距),但我認爲,如果一個結構在malloc'ed空間內,它保證其成員重疊其中的適當字節。 – supercat

1

沒有,沒有什麼是標準的保證。不過,您具體的編譯器實現可能會超出標準所做的保證。檢查您的文檔的所有細節。

+0

對齊要求不相關。'val'和'array'成員將具有相同的對齊要求,所以由對齊要求引起的對'val'的填充將與由對齊要求引起的對'array'元素的填充相同。該標準允許'val'和'array'之間的未命名填充,但實現不會插入填充以滿足對齊要求。 (假設它可能會插入填充以實現對齊優點,例如,如果它有助於將'array'與高速緩存行對齊,並且編譯器有理由相信這會有所裨益。) –

+0

足夠公平;第二句刪除。 –

0

嗯,你該結構的定義是2場,所以你可能compailer不使用它作爲11種元素的ARRY,所以你必須填寫你的Fileds因爲他們decleared。