gccで以下のソースをコンパイルすると、
int a3[][5] = {
0,1,2,3,4, // ★1
5,6,7,8,9
};
prog1.c:★1の行:5: warning: missing braces around initializer (初期値の並びに括弧が足りません)
というワーニングが出る。2次元配列を初期化するときは、
int a3[][5] = {
{0,1,2,3,4},
{5,6,7,8,9}
};
初期値の並びも2次元にする必要がある。3次元以上も同様。
ESCR Ver2.0 改訂版 組込みソフトウェア開発向け コーディング作法ガイド [C言語版] M2.1.1 にも「配列や構造体を0 以外で初期化する場合は、構造を示し、それに合わせるために波括弧 "{ }" を使用しなければならない。また、すべて0 以外の場合を除き、データは漏れなく記述する。」というルールが定められている。
話しはここから始まる。なお、これ以降のソースはすべてワーニングを除去してある。
int 5個の配列が入った構造体をtypedefしてみる。それを使った配列を初期化してみよう。
typedef struct { int array[5]; } INT5;
int a3[][5] = {
{0,1,2,3,4},
{5,6,7,8,9}
};
INT5 b3[] = {
{{0,1,2,3,4}}, // ★2
{{5,6,7,8,9}}
};
このように最終的には同じデータの並びになるものでも、
typedef struct {} したのでもう一段括弧が必要になる。
★2の行だと、 構造体の左括弧、配列の左括弧、整数5つ、配列の右括弧、構造体の右括弧
である。
さらに、2次元配列を繰り返して、3次元配列にしてみよう。
typedef struct { int array[5]; } INT5;
int a4[][2][5] = {
{{0,1,2,3,4},{5,6,7,8,9}},
{{10,11,12,13,14},{15,16,17,18,19}}
};
INT5 b4[][2] = {
{{{0,1,2,3,4}},{{5,6,7,8,9}}}, // ★3
{{{0,1,2,3,4}},{{5,6,7,8,9}}}
};
配列の次元があがったので、a4もb4も、もう一段括弧が必要になる。
★3の行だと、配列の左、
構造体の左、配列の左、整数5つ、配列の右、構造体の右、
構造体の左、配列の左、整数5つ、配列の右、構造体の右、
配列の右
となっていて、構造体が繰り返されていることがわかる。
typedef struct { }をもう一段増やしてみよう。上で定義したINT5が2つ入った構造体、INT10を定義する。
typedef struct { INT5 array[2]; } INT10;
int a4[][2][5] = {
{{0,1,2,3,4},{5,6,7,8,9}},
{{10,11,12,13,14},{15,16,17,18,19}}
};
INT10 c4[] = {
{{{{0,1,2,3,4}},{{5,6,7,8,9}}}},
{{{{10,11,12,13,14}},{{15,16,17,18,19}}}},
};
構造体の分だけ、括弧がもう一段必要になった。
typedefを入れ子にしないで、2次元配列をtypedefしてみる。
typedef struct { int array[2][5]; } INTW;
int a4[][2][5] = {
{{0,1,2,3,4},{5,6,7,8,9}},
{{10,11,12,13,14},{15,16,17,18,19}}
};
INTW d4[] = {
{{{0,1,2,3,4},{5,6,7,8,9}}},
{{{10,11,12,13,14},{15,16,17,18,19}}}
};
構造体1つのtypedefであれば、括弧は一段深くなるでOK。
確認のため、上記で出てきた配列のsizeofを求めてみた。intは4バイトなので、intが何個入っているかわかる。
sizeof(a3)= 40
sizeof(b3)= 40
sizeof(b4)= 80
sizeof(c4)= 80
sizeof(d4)= 80
おまけ
基本型の繰り返しであって構造体を使わないでも多次元配列が作れるような場合は、
typedef int INTA5[5];
INTA5 e5 = {1,2,3,4,5};
INTA5 e6[] = {
{0,1,2,3,4},
{5,6,7,8,9}
};
typedef int INTA25[2][5];
INTA25 f5 = {
{0,1,2,3,4},{5,6,7,8,9}
};
INTA25 f6[] = {
{{0,1,2,3,4},{5,6,7,8,9}},
{{10,11,12,13,14},{15,16,17,18,19}}
};
このようにtypedefして初期化することもできる。
これならtypedefしないときの初期化と同じデータの並びにできる。
e6とf5は同じデータの並びにでき、
a4とf6は同じデータの並びにできる。
なお、配列のサイズより、初期値の数が多かったら、
int a2[5] = {
0,1,2,3,4,5 //★4
};
prog8.c:★4の行:1: warning: excess elements in array initializer [enabled by default]
というワーニングになる。