2012-10-24 7 views
11

私は以下の構造を有すると仮定:パディングエリアをワイプすることが保証されている構造の初期化はゼロですか?

typedef struct 
{ 
    unsigned field1 :1; 
    unsigned field2 :1; 
    unsigned field3 :1; 
} mytype; 

最初の3ビットは使用できますが、sizeof(mytype)はパディングの29ビットを意味する4を返します。

mytype testfields = {0}; 

か:: 私の質問は、これらのパディングビットは、文で初期化され、ゼロであることを標準で保証されていることが前提に、次のmemcmp()を実行しても安全です

mytype myfields = {1, 1, 1}; 

このようなことをそのビット4..29はゼロになるため、比較には影響しません。

if (memcmp(&myfields, &testfields, sizeof(myfields)) == 0) 
    printf("Fields have no bits set\n"); 
else 
    printf("Fields have bits set\n"); 

答えて

11

を設定していないことを保証し。実際の標準は、C11は、指定:静的またはスレッド記憶域期間を持つオブジェクトは、その後、明示的に初期化 ない

場合:

  • ....

  • 集約の場合、これらの規則に従ってすべてのメンバーが(再帰的に) に初期化され、パディングはゼロビットに初期化されます。

これが唯一の最初のビューでは、静的記憶のオブジェクトのために保持します。しかし、その後、それはほかに言う:

はの配列を初期化するために使用されるリテラル 文字列内の要素または集合体のメンバー、または少ない文字があるよりも、中括弧で囲まれたリスト内の少ない初期化子がある場合既知のサイズは であり、配列内の要素であるため、残りの部分は、 であり、暗黙的に静的記憶域を持つオブジェクトと同じになります duration。

したがって、明示的に初期化されていないサブ構造内のパディングはゼロビットで初期化されます。

要約では、構造内のパディングの一部がゼロビットで初期化されていることが保証されています。このような混乱が意図的ではないと私は考えています。私はこれについての欠陥報告を提出します。

古いバージョンにはそれがまったくありませんでした。したがって、既存のほとんどのコンパイラでは、C11を実装していないため、さらに注意する必要があります。しかし、AFAIR、clangはすでにそれに代わって行います。

これは初期化のためにのみ保持されることにも注意してください。代入時には必ずしも余白がコピーされるとは限りません。

+2

+1、興味深い私はこの変化を認識していませんでした。 – ouah

+4

私はあなたがC11段落の先頭を追加する必要があると思います*自動保存期間を持つオブジェクトが明示的に初期化されていない場合、その値は不定です。静的またはスレッド記憶期間を持つオブジェクトが明示的に初期化されていない場合、*これは 'mytype testfields = {0};の埋め込みを保証するものではなく、' 0'に設定されます。 – ouah

+0

@ouah、実際には抜け穴があるようですが、あなたは正しいです。私はそれが意図されているとは思わないので、もう少し説明します。いい視点ね。 –

6

C99規格ではパッドを指定していませんdingビットはゼロに設定される。実際には、すべてのパディングビットの値が指定されていないため、パディングを代入でコピーする必要はありません。 (6)(n1570)6.2.6.1に

脚注51:

よって、例えば、構造の割り当ては、任意のパディングビットをコピーする必要はありません。

新しいC2011の標準 - その知識を共有するためのJens Gustedtのおかげで - 割り当てのための保証はまだありません明示的に初期化せずに、静的またはスレッド記憶域期間のオブジェクト内のパディングビットが0

に初期化されることを指定します。

+2

まあ、それはむしろ 'memcmp()'はパディングを持つ構造を比較するのは危険な方法でしょうか? – Benj

+0

@Benjはい、 'memcmp'はパディング効果のため安全ではありません。埋め込まれたビットは使用されていませんが、合法的にはアクセスできません。したがって、標準がパディングを義務付けているかどうかはどちらの方法でも問題にならないはずです。 –

+0

@KingsIndian:メモリが 'calloc()'やその他の手段で受け取られた場合、そのメモリに正当なアクセス権があります。一方、構造上のほとんどすべての操作は、その中の任意のパディングで好きなことをすることが許可されていると私は信じています。コードは構造体へのポインタを正当に使用して、その間に構造体にアクセスしなければその中のすべてのバイトをコピーすることができますが、システムがパディングバイトに関して保証する唯一の保証は、行き先の問題 – supercat

2

私の質問、文によって初期化され、ゼロであることを標準で保証これらのパディングビットですされています

パディングの値が指定されていない:

(C99,6.2.6.1p6) "値が、構造体または共用体型のオブジェクトに格納される場合(メンバーオブジェクトを含む)、任意のパディングバイトに対応するオブジェクト表現のバイト未指定の値をとる」

EDIT:参照イェンスGustedt answer、C11は現在、パディングがはい(まれ)特定の状況で0