I’m working on an exercise in K&R (ex. 5–9) and I was trying
to convert the original program’s 2D array of
static char daytab[2][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
13個のintの配列へのポインタを使う
static char (*daytab)[13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
しかし、コンパイラは 警告:スカラー初期化子の余分な要素
を表示します。
Googling did not help and even K&R writes when passing the
array to a function,
myFunction(int daytab[2][13]) {...}
〜と同じです
myFunction(int (*daytab)[13]) {...}
2つは部分的に同等です。違いは次のとおりです。
static char daytab[2][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
2次元配列を宣言します。この配列には、配列のスペースを確保し、そのメモリを参照する daytab
を確保します。しかしながら:
static char (*daytab)[13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
…ポインタだけを宣言します。したがって、期待どおりに動作しない配列初期化子でポインタを初期化しようとしています。配列はありません。配列にはメモリが用意されていません。代わりに、イニシャライザの最初の数値がポインタ
daytab
に割り当てられているだけです。警告が表示され、破棄されたばかりの追加値がたくさん指定されています。初期化子の最初の数字は
0
なので、 daytab
を NULL
に設定するのは、
したがって、このような初期化を行う場合は、最初のバージョンを使用します。これは、2番目のバージョンで明示的に宣言したものと同じポインタ型に崩壊するため、同じ方法で使用できます。配列ポインタを持つ2番目のバージョンは、配列を動的に割り当てるか、すでに存在する別の配列への参照を取得する場合に必要です。
だからあなたはこれを行うことができます:
static char arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
static char (*ptr)[3] = NULL;
ptr = arr;
… ptr
と arr
を同じ意味で使用してください。またはこれ:
static char (*ptr)[3] = NULL;
ptr = malloc(2 * sizeof(*ptr));
…動的に割り当てられた2次元配列(1D配列へのポインタの配列ではなく、実際の2D配列)を取得する。もちろん、その場合は初期化されません。
2つのバリエーションの「同値」は、2D配列が最初の要素へのポインタに減衰するとき、2番目のバリエーションで宣言されたポインタの型に減衰することを意味します。ポインタバージョンが実際に配列を指すと、その2つは同等です。しかし、2D配列バージョンでは、配列のメモリが設定されています。ポインタ宣言ではそうではありません。ポインタには、2D配列変数ではできない新しい値(別の配列をポイント)を割り当てることができます。
C99では、少なくとも( static
ではなく)これを行うことができます:
char (*daytab)[13] = (char [][13]){
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};