11

次の構造があるとします。

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

最初の 3 ビットは使用できますが、29 ビットのパディングを意味sizeof(mytype)する戻ります。4私の質問は、これらのパディングビットは、ステートメントによって初期化されたゼロであることが標準によって保証されているかということです:

mytype testfields = {0};

また:

mytype myfields = {1, 1, 1};

memcmp()ビット 4..29 が 0 であり、したがって比較に影響しないという前提で、以下を安全に実行できるようにします。

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

3 に答える 3

11

はいといいえ。実際の標準である C11 では、次のように指定されています。

静的またはスレッド ストレージ期間を持つオブジェクトが明示的に初期化されていない場合は、次のようになります。

  • ....

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

したがって、これは最初のビューで静的ストレージのオブジェクトにのみ当てはまります。しかし、その後、さらに次のように述べています。

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

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

要約では、構造物の一部のパディングがゼロビットの初期化されていることが保証されていますが、一部はそうではありません。このような混乱は意図的であるとは思わないので、このために欠陥レポートを提出します。

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

また、これは初期化にのみ適用されることに注意してください。パディングは、割り当て時に必ずしもコピーされるとは限りません。

于 2012-10-24T19:45:27.240 に答える
6

C99 標準では、パディング ビットを 0 に設定することは指定されていません。実際、割り当てでパディングをコピーする必要がないように、パディングビットの値は指定されていないことが明確に述べられています。

脚注 51 から 6.2.6.1 (6) (n1570):

したがって、たとえば、構造体の割り当てでは、パディング ビットをコピーする必要はありません。

新しい C2011 標準 (その知識を共有してくれたJens Gustedtに感謝) では、明示的な初期化を行わない静的またはスレッド ストレージ期間のオブジェクトのパディング ビットを 0 に初期化することを指定しています。

割り当ての保証はまだありません。

于 2012-10-24T19:33:30.987 に答える
2

私の質問は、これらのパディングビットは、ステートメントによって初期化されたゼロであることが標準によって保証されているかということです:

いいえ。

パディングの値は指定されていません。

(C99、6.2.6.1p6) 「メンバー オブジェクトを含め、構造体または共用体型のオブジェクトに値が格納されている場合、パディング バイトに対応するオブジェクト表現のバイトは指定されていない値を取ります」

編集: Jens Gustedt answer0を参照してください。C11 は、(まれな) 特定の状況でパディングが設定されることを保証するようになりました

于 2012-10-24T19:40:27.470 に答える