さて、作成したのは変数配列ではありません。サイズがわからない配列です。その配列は不完全な型を持っているため、C++ では定義できません。あなたができることは、それをextern
前に置いて単なる宣言にすることです。
extern coords MyCoords[];
次に、それを初期化する .cpp ファイルで、その配列を作成 (定義) できます。もちろん、関数の外側の名前空間スコープで行う必要があることに注意してください。
coords MyCoords[] = {{1, 2}, {3, 4}, ... };
必要なのは、コンパイル時ではなく実行時にサイズが不明な配列である場合は、次を使用する必要がありますstd::vector
。
std::vector< coords > MyCoords;
その後、それを埋める場合は、
MyCoords.push_back( coords(1, 2) );
MyCoords.push_back( coords(3, 4) );
....
または、ローカル配列を作成し、その配列の要素のコピーを使用してベクトルを初期化します。
coords c[] = ....;
MyCoords.insert(MyCoords.end(), c, c + sizeof c / sizeof *c);
C では、C++ とは少し異なります。次元が不明な配列を定義できます。何が起こるかというと、それは「暫定的な」定義であると見なされます。ファイルの末尾 (より正確には、そのファイルとそれに含まれるすべてのファイルである翻訳単位の最後) に、サイズを含むそのファイルの後続の定義がない場合、サイズは実寸とさせて頂いております1
。ただし、C++ には暫定的な定義がなく、サイズを含まず、サイズを判別できる初期化子を含まない定義は、無効な C++ プログラムです。
あなたのコードがグラジーになる理由のために、あなたはやっています
MyCoords[0] = {0, 0}
コンパイラは次のように読み取ります。
-> Set LHS to RHS
-> -> LHS is a variable of type `coords`. Fine
-> -> RHS is... hmm, `{0, 0}`. What the heck is it??
ご覧のとおり、コンパイラは右辺が何を意味するのか見当がつきません。そのため、C99 (1999 年版の C) では、いわゆる複合リテラルが導入されました。それはあなたが書くことを可能にします
MyCoords[0] = (coords){0, 0};
そして、それは実際にあなたがやりたいことをします - タイプの右側の値を作成し、coord
それを左側に割り当てます。しかし、すでに互換性の理由から (多くの C コンパイラは合理的な C99 準拠ではなく、C++ も C89 も複合リテラルをサポートしていません)、以前に示した方法のいずれかを使用する必要があります。