1. ホーム
  2. c

[解決済み】int型配列へのポインタのスカラ・イニシャライザの過剰要素

2022-02-12 20:21:30

質問

K&Rの演習問題(例5-9)をやっているのですが、元のプログラムの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}
};

のような 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}
};

しかし、コンパイラは次のように表示します。 警告:スカラ・イニシャライザに過剰な要素があります .

ググっても解決せず、K&Rでも関数に配列を渡すと書き込みます。

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;

...そして ptrarr を交換することができます。 あるいはこうも。

static char (*ptr)[3] = NULL;

ptr = malloc(2 * sizeof(*ptr));

...動的に割り当てられた2次元配列(1次元配列へのポインタの配列ではなく、本当の2次元配列)を取得します。 もちろん、その場合は初期化されません。

2つのバリエーションの"equivalence"は、2D配列がその最初の要素へのポインタに減衰するとき、2番目のバリエーションで宣言されたポインタのタイプに減衰することを意味するだけです。 ポインタ版が実際に配列を指すようになれば、この2つは等価です。 しかし、2次元配列では配列のメモリが設定され、ポインタの宣言では設定されません。また、2次元配列の変数ではできない新しい値(別の配列を指す)をポインタに代入することができます。

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}
};