2016-11-13 8 views
3

?たとえば、このプログラムは明確に定義されていますか?同じフィールドシーケンス内のフィールドは同じオフセットを持っていますか?レコードタイプ<em>T1</em>と<em>T2</em>は、同一であり、最初の<em>のk</em>フィールドがこれらのフィールドは、同じオフセットすることが保証されている場合は

typedef struct { 
    int x, y; 
} Shape; 

typedef struct { 
    int x, y; 
    int w, h; 
} Rectangle; 

static void InitShape(Shape *s) 
{ 
    s->x = 0; 
    s->y = 0; 
} 

int main(void) 
{ 
    Rectangle r; 

    InitShape((Shape *) &r); 
    r.w = 1; 
    r.h = 1; 
    return 0; 
} 

編集:(代わりタイプ形状の単一のフィールド塩基の)私のプロジェクトでCコードが生成され、形状から個々のフィールド長方形を含む他の場所コードを簡素化します。

+0

おそらく - 私はそれに賭けないでしょう。なぜ彼らは彼らがそうすると思いますか? –

+1

["Struct inheritance in C"](http://stackoverflow.com/questions/1114349/struct-inheritance-in-c)をご覧ください。 – Schwern

+0

あるタイプを別のタイプにキャストしても、厳密なエイリアシングルールに違反していませんか? downvoted、その答えは、他の構造体に1つの構造体を含めることをお勧めします。 –

答えて

3

プログラムが定義されていません。

C標準では、構造体の最初のメンバーの前にはパディングが存在しないことが保証されています。これは、構造体ShapeとRectangleのメンバーxとyの間に異なる量のパディングが存在する可能性があり、Rectangle型の1つのオブジェクトがShape型として再解釈されると、同じオフセットのメンバーを持たない可能性があることを意味します。

これは、両方のメンバーが同じオフセットを持ち、静的なアサーションを使用して強制することができると予想するのが妥当であるため、主な問題ではありません。

主な問題は厳密なエイリアシングです。型が別名となる条件がありますが、これらの2つの型はいずれも満たされません。 Rectangle型とShape型は互換性がなく、Rectangle型にはShape型のメンバが含まれていません。

したがって、型Rectangleを型Shape:InitShape((Shape *) &r);として再解釈すると、未定義の動作が発生します。


6.5式7
オブジェクトは、その格納された値は、一 、次のタイプ有する左辺式によってのみアクセスしなければならない:
- タイプオブジェクトの有効型と互換性を、
- (subaggregate又は含ま組合のメンバー、再帰的に、など)その

メンバー
+0

私は正解についてdownvotesと一緒に建設的なコメントを読むのが大好きです。 – 2501

0

これは機能します。この関数は、構造体のxおよびyフィールドを形状のように初期化します。私はそれに似た何かを使っている多くのプロジェクトを見てきました。それらを区別するために同じ最初のフィールドを持ついくつかの構造を作成します(クールソラールによって書かれた愛のゲームを見てください)。 。

しかし、私は別のやり方をしています。 、

typedef struct { 
    Shape s; 
    int w, h; 
} Rectangle; 

この方法では、init関数を呼び出すときは、形状として長方形を型キャストするか、または内部形状sを渡す:初期データが同じであるとき、私は実際にこのような長方形の構造を変更したいです関数に渡します。私の心の中では、それはそれをより明確にします。さらに良いことに、私が代わりにタイプのために定義して、フィールドが列挙型に変化するだろうが、のための列挙型を使用したい

#include <stdint.h> 

#define TYPE_SHAPE 0U 
#define TYPE_RECTANGLE 1U 

typedef struct { 
    char *name; 
    char *descrition; 
    uit8_t type; 
} Info; 

typedef struct { 
    Info info; 
    int x, y; 
} Shape; 

typedef struct { 
    Info info; 
    Shape s; 
    int w,h; 
} 

void Init(Info *block) { 
    if(block->type == TYPE_SHAPE) { 
     //initialize it 
    } else { 
     //do something elese 
    } 
} 

は、私がこれまでより多くの類似した何かをしたい、さらに行きますこのサイズは私はそれが大丈夫だと思います。

IF矩形と形状の両方のxとyフィールドが同じものを意味する場合、方法は問題なく動作します。

PS:それがうまくいくかどうかをテストするために上記をコンパイルしていません。ちょうどアイデアを与えることです。

+0

私のこの技術を応用すると、Cコードが生成されます。この場合、拡張型の基本型の個々のフィールドを生成する方が理にかなっています。 –

-1

Tのうち、前述のタイプのいずれかを含む凝集体または共用タイプC99標準では、共通初期シーケンス保証を使用するコードでは、コンパイル時にコンパイラにエイリアスがあることを知らせるために、アクセス時に構造を含む完全なユニオンタイプを表示する必要があるという要件を追加(およびC11は保持)しています。

標準は、それが労働組合のタイプを使用して行うことがアクセスする必要はありませんが、GCCの作者は、どちらかと考えているか完全ユニオンタイプはなるように指定する理由はありませんという事実にもかかわらず、それがないことをふりこのような解釈の下では、Common Initial Sequenceの保証は事実上無価値になります。

私は実際に標準に従うのコンパイラとの互換性を確保するためにunion型宣言を追加することをお勧めしますが、GCCの著者があからさまプロセスに拒否しているので、私はまた、gccを使用している場合、あなたは関係なく、-fno-strict-aliasを使用することをお勧めします規格に準拠した厳密に準拠したコード。

関連する問題