4

実験 (Clang および GCC で、-O2 および -O0 を使用)から、次のコードで

typedef struct foo_s { int i; int j; } foo_t;
int main(void) {
    foo_t foo = {.i = 42};
    ...

foo.j は自動的にゼロになります。

C99以降で保証されていますか、それともコンパイラ固有の実装の詳細ですか?

注:スタックの下の無効なメモリに、foo が後で指定されるアドレスに 0xFF を書き込もうとさえしました。

更新: これは、スタックの下のメモリにたまたまゼロが含まれているためであるというコメントがいくつかあります。次のコードは、これが当てはまらないことを確認し、GCC -O0 がメモリをゼロにしていることを証明する可能性があります。

-7 と -6 のオフセットは、コンパイラに依存します。それらは Clang で異なる必要がありました。

typedef struct foo_s { int i; int j; } foo_t;

int main(void) {
    int r;
    int *badstack0 = &r - 7;
    int *badstack1 = &r - 6;

    *badstack0 = 0xFF; // write to invalid ram, below stack
    printf("badstack0 %p, val: %2X\n", badstack0, *badstack0);
    *badstack1 = 0xEE; // write to invalid ram, below stack
    printf("badstack1 %p, val: %2X\n", badstack1, *badstack1);

    // struct test
    foo_t foo = {.i = 42};
    printf("&foo.i %p\n", &foo.i);
    printf("&foo.j %p\n", &foo.j);
    printf("struct test: i:%i j:%i\n", foo.i, foo.j);
    return 0;
}

出力:

badstack0 0x7fff221e2e80, val: FF
badstack1 0x7fff221e2e84, val: EE
&foo.i 0x7fff221e2e80
&foo.j 0x7fff221e2e84
struct test: i:42 j:0
4

2 に答える 2

9

初期化子を指定すると、明示的に言及されていないメンバーは静的であるかのように初期化されます。これは、6.7.9 (19) の標準によって保証されています。

初期化はイニシャライザ リストの順序で行われます。特定のサブオブジェクトに指定された各イニシャライザは、同じサブオブジェクトの以前にリストされたイニシャライザをオーバーライドします。明示的に初期化されていないすべてのサブオブジェクトは、静的ストレージ期間を持つオブジェクトと同じように暗黙的に初期化されます

(強調は私が追加)

どのメンバーも初期化しない場合、すべてのメンバーの値は不確定です。

于 2013-02-28T14:42:17.570 に答える
4

Daniel Fischer's answer で引用されているように、C は、配列/構造体/共用体* の少なくとも 1 つのメンバーが明示的に初期化されている限り、他のすべてのメンバーが静的ストレージ期間を持っているかのように初期化されることを保証します。つまり、他のすべてのメンバーは自動的にゼロまたは NULL に設定されます。

配列/構造体/共用体のストレージ タイプは重要ではありません。ストレージ期間が自動であるか静的であるかに関係なく、同じ規則に従って初期化されます。

これは C99 以降に固有のものではなく、C には常にこの要件がありました。適合するすべての C コンパイラはこの規則に従います。これは標準であり、実装定義ではありません。

これは、「デバッグ リリース」ゼロアウトとは関係ありません。

実際のところ、このルールは、次のように記述して配列全体をゼロにできる理由を説明しています。

int array[100] = {0}.

このコードは、「最初の要素をゼロに初期化し、残りの 99 個の要素を静的な保存期間があるかのように初期化する、つまり、それらもゼロにする」ことを意味します。


(*) これら 3 つの型は、C 標準では正式に「集合型」と呼ばれています。

于 2013-02-28T15:15:38.897 に答える