なぜ私は、配列の3つのレベルを初期化するための括弧の3つのレベルを必要としませんか?

SIRBUカタリナ:

私はこの例に出会いました

struct sct
{
    int t[2];
};

struct str
{
    sct t[2];
};

int main()
{
    str t[2] = { {0, 2, 4, 6}, {1, 3, 5, 7} }; //Who does this work?

    cout << t[1].t[0].t[1] << t[0].t[1].t[0];     

    return 0;
}

このコンパイルして実行されます罰金。これは、出力を提供します34

私は、初期化の構文は次のようになり予想しました:

str t[2] = {  { {0, 2},{4, 6} }, { {1, 3},{5, 7} }   };

の代わりに

 { {0, 2, 4, 6}, {1, 3, 5, 7} };

しかし、これは与えました:

In function 'int main()':
error: too many initializers for 'str'

誰かが理由を説明することはできますか?

これは私がこれを見る方法を説明するための画像です: ここでは、画像の説明を入力します。

どのように私はそれがネストされた構造体を初期化することになると考えなければなりませんか?

ドミトリChubarov:

この単純なタイプミスのように見えるが、状況はステップでそれステップに取り組むための複雑十分です。

まず、私は仕事に思えるソリューションを表示してみましょう:

int main()
{
    str t[2] = { { { {0, 2}, {4, 6} } }, { { {1, 3}, {5, 7} } } };
    cout << t[1].t[0].t[1] << t[0].t[1].t[0] << endl;

    return 0;
}

配列持って、私たちはそれほどstrの配列を保持していますsct

のは、後者から始めましょう。あなたは、配列の初期化sctのようなものとします:

sct x[2] = { {0, 1}, {2, 3} };

Now for a single instance of str you could go with

str y = { { {0, 2}, {4, 6} } };

What remains for str t[2] is to arrange two copies of str initializing expressions inside curly brackets:

str t[2] = { { { {0, 2}, {4, 6} } }, { { {1, 3}, {5, 7} } } };

Edited: On the first reading I misunderstood the question. After the post was updated it became clear that the question is on why it is possible to shed two pair of braces but shedding just one pair results in a syntax error.

To understand how the parser is interpreting the code you might like to look at the parse tree. You can make gcc dump trees at several stages of the parser with -fdump-tree-... options. Here -fdump-tree-original may be useful.

To avoid additional confusion let's make sure the elements of the structures have different names:

struct sct
{
    int a[2];
};

struct str
{
    sct b[2];
};

Here is the output I got with GCC 7.5 from

>>>> CODE:
str t[2] = { { 0, 2, 4, 6 }, { 1, 3, 5, 7 } };
>>>> tree enabled by -tree-original
struct str t[2] = {{.b={{.a={0, 2}}, {.a={4, 6}}}}, {.b={{.a={1, 3}}, {.a={5, 7}}}}};

あなたは、コンパイラは、各構造のための初期化表現を中心に、それぞれの名前のフィールドの初期化の式の周りに暗黙のブラケットを追加していることがわかります。

今、コンパイルに失敗した表現を考えてみます。

str t[2] = {  { {0, 2},{4, 6} }, { {1, 3},{5, 7} }   };

この式のツリーは次のようになり、上位レベル

/*Step 1: */ struct str t[2] = { {.b={0, 2}, {4, 6} }, {.b={1, 3}, {5, 7} } };

bが配列の場合でもsct、私たちはとそれを初期化しようとする{0,2}取得します

sct b[2] = {0, 2};

これは、に展開します

struct sct b[2] = {{.a={0, 2} }};

これは、有効なC ++で配列の最初の要素が明示的に初期化され、2番目の要素がゼロで暗黙的に初期化されているので。

この知識で、私たちは以下のツリーを取得します

/*Step 2: */ struct str t[2] = { {.b={{.a={0, 2} }}, {4, 6} }, {.b={{.a={1, 3} }}, {5, 7} } };

今、私たちは次が残されています。

 struct str z = { { { {0,2} }, { {0,0} } }, {4, 6} };

そして、コンパイラは当然文句:

 error: too many initializers for ‘str’

最終チェックとして次の宣言を検討

 struct sxc
 {
     sct b[2];
     int c[2];
 }

 struct sxc z = { {0,2} , {4, 6} };

次のような構造で、このコンパイルした結果:

 { .b = { { .a={0,2} }, { .a={0,0} } }, .c={4, 6} }

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=30406&siteId=1