2016-11-21 1 views
6

私は、コンパイラがいくつかのパディングバイトを構造体に追加するかもしれないことを知っています。しかし、コンパイラが構造体内の変数から読み取ったことがないことがわかると、構造体のサイズがメンバーの合計サイズよりも小さくなる可能性はありますか?structは、そのコンポーネントの合計よりも小さくすることはできますか?

struct Foo_T 
{ 
    int a; 
    intmax_t b; 
}; 


void bar(void) 
{ 
    struct Foo_T foo; 
    foo.a=rand(); 
    someFunction(foo.a); 
    //i never access foo.b, only foo.a 
    if(sizeof(foo)< sizeof(int)+sizeof(intmax_t)) 
    { 
     //is it possible that we can end here? 
    } 
} 
+3

コンパイラがいくつかのパディングを追加したり、かなりの最適化を行うことは可能ですが、構造体のメンバーを削除することはできません。これは、特に構造を外部関数に渡す場合には、非常に難しいことです。 –

+0

この便利なトピックを読む:http://stackoverflow.com/questions/9486364/why-cant-c-compilers-rearrange-struct-members-to-eliminate-alignment-padding – Fefux

+0

C++でコンパイラは空のベースはできませんサイズは0ですが、派生クラスでは空のベースを切り捨てることができるため、子クラスのサイズはベースの合計サイズとそれ自身のデータよりも小さくなります –

答えて

7

いいえ、これはC standardで禁止されています。 C11で、セクション6.7.2.1は、このステートメントを含む:

15構造オブジェクト内、非ビットフィールドメンバーとビットフィールドが順に を増やすアドレスを持って存在する ユニット彼らは宣言されています。 [...] 内に構造体オブジェクトの名前のないパディングがありますが、先頭にはありません。

structのメンバーを削除すると、メンバーの宣言された順番が増えるという要件に違反することになります。

+0

これは、メンバーが宣言された順序で割り当てられなければならない。いくつかのコンパイラがここの場合のように構造体の最後の項目を削除すると、それは引用されたテキストに違反しません。関連する部分はむしろ、「抽象機械」の基本的な挙動と、どのような最適化が可能であるかを記述した規格の早い段階で見つかっています。 – Lundin

+0

構造体の一部のメンバーに決してアクセスしない場合、要件が違反していることをどのように知っていますか?それはコードの観察可能な振る舞いに影響を及ぼさないであろうし、したがって、「あたかも」のルールの下では完全に合法であろう。 – AnT

3

いいえ、できません。 sizeof(foo)を取るときは、少なくともsizeof(int) + sizeof(intmax_t)になると予想されます。コンパイラによってサイズが小さくなった場合、プログラムの動作に間違った影響を与えますが、これは許されません。

予約済みハードウェアレジスタが使用されないことを保証するため、または正しい位置合わせを保証するために、プレースホルダ「ダミー」として最後のメンバを配置するとします。コンパイラがそのようなメンバを削除すると、プログラムが壊れてしまいます。

0

構造体が自動変数または静的変数で宣言されていて、構造体もその一部もアドレスが取得されず、コンパイラが100%理解できない方法で使用されていない場合、コンパイラはレイアウトを変更できます構造体を使用するすべてのコードがそれに応じて調整されている場合は、構造体の重要なことは、言語外のメカニズム(例えば、デバッガでメモリレイアウトを見る、または定義されていないメモリ領域にアクセスするなど)を使用する以外は、コンパイラがそのようなことを行うかどうかをコードが判断できる方法がないことです。

0

絶対にではないです。

コンパイラはどのようにして明日の書き込みを予期することができますか? の現在のソースコードはではなく、であるという事実は、その要素が構造体のその部分にアクセスしようとするソースコードが決して存在しないことを保証するものではありません。

関連する問題