2

次のコードはコンパイルされません。

int main() {
  int a[][] = { { 0, 1 },
                { 2, 3 } };
}

生成されるエラーメッセージは

error: declaration of 'a' as multidimensional array must have bounds for all dimensions except the first
int a[][] = { { 0, 1 },
           ^

これは規格で指定されていますか?もしそうなら、それはなぜですか?ここで境界を推測するのは非常に簡単だと思います。

4

1 に答える 1

4

これは規格で指定されていますか?

まあ、そうだろう。

§8.3.4/3 複数の「array of」仕様が隣接している場合、多次元配列型が作成されます。配列の境界を指定する最初の定数式のみを省略できます。不完全なオブジェクト型が許可されている宣言に加えて、関数パラメーターの宣言では、場合によっては配列バインドが省略される場合があります (8.3.5)。宣言子の後に初期化子が続く場合は、バインドされた配列も省略できます(8.5)。この場合、境界は、N提供された初期要素 (たとえば、) の数から計算され (8.5.1)、の識別子の型Dは「の配列」です。N T」。さらに、境界が指定されたのと同じスコープ内にエンティティの前の宣言がある場合、省略された配列境界は、その前の宣言と同じであると見なされます。クラス。

もしそうなら、それはなぜですか?

たとえば、不完全な型から配列を構築することはできません (voidたとえば)。境界が不明な配列は、不完全な型の 1 つです。

§8.3.4/1 ... 配列型のオブジェクトに、連続して割り当てられた型 の空でないNサブオブジェクトのセットが含まれていTます。以下に示す場合を除き、定数式が省略されている場合、 の識別子の型は、不完全なオブジェクト型である「D の未知の境界の派生宣言子型リスト配列」です。T...

§8.3.4/2 配列は、基本型 ( を除くvoid) の 1 つ、ポインター、メンバーへのポインター、クラス、列挙型、または別の配列から構築できます。

さらに:

§3.9 宣言されているが定義されていないクラス、特定のコンテキスト (7.2) での列挙型、または未知のサイズまたは不完全な要素型の配列は、不完全に定義されたオブジェクト型です。45 ...

45) 不完全に定義されたオブジェクト型のインスタンスのサイズとレイアウトは不明です。

ここで境界を推測するのは非常に簡単だと思います。

コンパイラには魔法の力があるという、初心者が犯すよくある間違いがあります。コンパイラは、すでに持っている情報を処理します。何もないところから情報を作成するわけではありません。サイズが不明なオブジェクトを作成するように要求した場合、それは単純にできません。次の例を参照してください。

省略できるのは最内次元のみです。配列内の要素のサイズは、配列変数に指定された型から推測されます。したがって、要素の型には既知のサイズが必要です。

  • char a[] = { ... };サイズ1 (8 ビット)の要素 (例: a[0])を持ち、サイズが不明です。
  • char a[6] = { ... };要素のサイズは 1 で、サイズは 6 です。
  • char a[][6] = { ... };サイズ6 の要素 (たとえばa[0]、配列)があり、サイズが不明です。
  • char a[10][6] = { ... };にはサイズ6の要素があり、サイズは 60 です。

禁止されている:

  • char a[10][] = { ... };未知のサイズの要素が 10 個あります。
  • char a[][] = { ... };未知のサイズの未知数の要素を持つことになります。

ソース

于 2016-01-24T07:33:54.663 に答える