これは単純なタイプミスのように見えますが、状況は段階的にそれに取り組むのに十分複雑です。
最初に、うまくいくと思われるソリューションを示します。
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} };
今のstr
あなたの単一のインスタンスのために行くことができます
str y = { { {0, 2}, {4, 6} } };
残っているのstr t[2]
は、str
中括弧内に初期化式の2つのコピーを配置することです。
str t[2] = { { { {0, 2}, {4, 6} } }, { { {1, 3}, {5, 7} } } };
編集:私は最初の読書で質問を誤解しました。投稿が更新された後、2組のブレースを削除することが可能であるのに、1組だけを削除すると構文エラーが発生する理由が問題であることが明らかになりました。
パーサーがコードをどのように解釈しているかを理解するには、解析ツリーを調べてください。-fdump-tree-...
オプションを使用して、パーサーのいくつかの段階でgccダンプツリーを作成できます。ここ-fdump-tree-original
が役に立つかもしれません。
追加の混乱を避けるために、構造体の要素が異なる名前であることを確認しましょう:
struct sct
{
int a[2];
};
struct str
{
sct b[2];
};
これは私がGCC 7.5で得た出力です
>>>> 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} }};
配列の最初の要素は明示的に初期化され、2番目の要素は暗黙的にゼロで初期化されるため、これは有効なC ++です。
この知識により、次のツリーが得られます
/*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} }