2011-10-11 8 views
7

このコードはC標準によって保証されていますか?

struct Node { 
    int a, b, c; 
}; 

struct DerivedNode { 
    struct Node base; 
    int d, e, f; 
}; 

その後、あなたは、このようにそれらへのポインタを使用することができます:

struct DerivedNode myDerivedNode; 
struct Node *regularNode = (struct Node *) &myDerivedNode; 

regularNode->a = 3; 

つまり、a, b, cのためのアドレスオフセットは、内の同じです

私はあなたがこのように二つの構造体を宣言する場合は読んだことがstruct Nodestruct DerivedNode。だから、ノードポインタが正常に取られるでしょうどこでも強制的に(struct Node *) -cast DerivedNodeポインタを渡すことができ、それのうち多型の種類を取得することができます。

私の質問は、この動作が保証されているかどうかです。私はいくつかの奇妙なメモリアラインメントの問題があることを知っているし、コンパイラは時々メモリのより良いパッキングを達成するためにフィールドを並べ替えます。 baseフィールドは、struct DerivedNodeの始め以外のどこにでも置かれますか?

+0

あなたはいくつかの場所で 'struct'キーワードを忘れましたか? –

+0

@Jensああ、おそらく。申し訳ありません –

答えて

13

これは、標準で動作することが保証されています。構造体のメンバは、指定した順にレイアウトさと第1部材は、常にANSI C標準から0

関連抜粋オフセットに表示されています。

構造の配列からなるタイプですメンバーは、その記憶域が順序付けられた順序で割り当てられます。

これは、メンバーが順番にレイアウトされていることを示しています。

構造体オブジェクト内に名前のないパディングがありますが、先頭にはないことがあります。

はザは第一部材に配置されていることを意味するオフセット0

注:TC3 2007年9月ドラフト:標準抜粋は、ISO/IEC 9899のセクション6.7.2.1から採取しました。

3

デビッド氏はbaseDerivedNodeの最初の要素のままである限り保証しています。

しかし、これは一般的に悪いことです。私はあなたが後であなたの構造を変更する場合に発生しやすいより明確にし、少ない誤差である

struct Node *regularNode = &myDerivNode.base; 

を言うことができないくらいの状況を把握することはできません。

+0

+1私はこれに完全に同意します。 –

+0

状況は私がデータ構造クラスに入っていて、1975年にバイナリ検索から1つのブランチを取り除いてしまったことです。 :P –

1

これはあなたの質問に答えることはできませんが、標準のANSI(ISO)Cを書いている人はgcc -pedanticまたは-pedantic-errorsでコードをコンパイルできます。これらのオプションは、非標準のコード行で警告/エラーをコンパイルする必要があります。 man gccから、これは100%有効ではないこと

注:

[-pedantic]いくつかの非ISOプラクティスを見つけ、すべてではない---のみISO C Aを必要とする のもの診断、および 診断が追加されたその他のものが含まれます。