OKWAVEのAI「あい」が美容・健康の悩みに最適な回答をご提案!
-PR-
解決
済み

引数に二重配列のある関数について

  • すぐに回答を!
  • 質問No.120070
  • 閲覧数331
  • ありがとう数1
  • 気になる数0
  • 回答数4
  • コメント数0

void calc(int *a,int b,int c){
a[0]=b+c;
a[1]=b-c;
}
void main(void){
int x[2];
int y=2,z=5;
calc(x,y,z);
printf("x[0]=%d,x[1]=%d\n",x[0],x[1]);
}
上のように引数が普通の配列の関数ならできるのですが,
引数が下のような多重配列になるとエラーが出てしまいできません。
void keisan(int **a,int b,int c){
a[0][0]=b+c;
a[0][1]=b-c;
a[1][0]=b*c;
a[1][1]=b/c;
}

void main(void){
int x[2][2];
keisan(x,6,2);
printf("x[0][0]=%d,x[0][1]=%d\n",x[0][0],x[0][1]);
printf("x[1][0]=%d,x[1][1]=%d\n",x[1][0],x[1][1]);
}

引数に多重配列を使った場合の関数の作り方について教えてください.
お願いいたします.
通報する
  • 回答数4
  • 気になる
    質問をブックマークします。
    マイページでまとめて確認できます。

質問者が選んだベストアンサー

  • 回答No.3
レベル12

ベストアンサー率 75% (398/526)

 2次元配列というのは、2つの添え字を使って表のイメージでデータを扱えるので大変便利なのですが、結局メモリの中では1次元配列と同じように、直線的にデータが配置されています。
 つまり
  int x[2][2];
  x[0][0] = 1; x[0][1] = 2;
  x[1][0] = 3; x[1][1] = 4;
と定義されているとすると、メモリの中では、
  x
  1 2 3 4
となっています。
 ためしに x[0][2] を表示してみると、3 が表示されます。

 この2次元配列xは、1次元目(1番右)の要素数が2個であると宣言されているので、x[1][0] とアクセスするだけで、xから3番目のデータを取り出すことができるわけです。
 ところが関数keisanで宣言されている int **a には、この「要素数の情報」がないため、 a[1][0] がメモリのどこにアクセスすればよいのか分からないので、エラーとなってしまうのです。

 これを解決するには、2次元配列を受け取る変数の宣言に、1次元目の要素数情報を与えてやればよいわけです。宣言方法は次の通りです。
  void keisan(int a[ ][2], int b, int c);

 仮引数の宣言で配列を宣言しても、同等の配列へのポインタになるので、配列が丸々コピーされることはありません。
 2次元目の要素が空になっていますが、配列が用意されるわけではないので、ここには2を入れても全く意味がありません。入れても無視されます。

 ちなみにsssoheiさんの int a[2][ ] や、int a[2][ ] は文法違反です。
また int *a[2] という宣言は、ポインタ配列を受け取る場合の書き方で、やはりこの場合はエラーになります。

 3次元以上の配列の場合でも、考え方は同じです。ただし要素数を省略できるのは、1番左だけということを覚えておいてください。
 下記は、int x[2][3][4]; と宣言された変数aを受け取るための引数の宣言です。
  void func(int a[ ][3][4]);
-PR-
-PR-

その他の回答 (全3件)

  • 回答No.1

コンパイルかけてみたところ、以下のようなエラーでした。 ==================================================================================== "test.c", 54 行目: 警告: 1 番目の引数は、プロトタイプ宣言の型と互換性がありません: プロトタイプ: pointer to ...続きを読む
コンパイルかけてみたところ、以下のようなエラーでした。
====================================================================================
"test.c", 54 行目: 警告: 1 番目の引数は、プロトタイプ宣言の型と互換性がありません:
プロトタイプ: pointer to pointer to int : "test.c", 41 行目
引数 : pointer to array[2] of int
====================================================================================

関数のほうはintのポインタのポインタを引数として求めているのに、
mainはintの配列を引数として渡しているからこのエラーが出たのだと思います。

そこで以下のように関数の宣言を変えてみたところ、うまくいきました。

void keisan(int **a,int b,int c)

void keisan(int a[2][2],int b,int c)
  • 回答No.2
レベル9

ベストアンサー率 33% (33/98)

int ** ではコンパイラはどのくらいの大きさの 配列なのかが分からないので、コンパイルエラーが出ます。 そこで、 int a[2][] のように、記述する必要があります。 三重の場合は int a[2][2][] の様に記述します。 もちろん、 int a[2][2] の様に記述しても構いませんし、 int* a[2] でも大丈夫だと思います^^; 記憶の中のものなので ...続きを読む
int ** ではコンパイラはどのくらいの大きさの
配列なのかが分からないので、コンパイルエラーが出ます。

そこで、
int a[2][] のように、記述する必要があります。
三重の場合は
int a[2][2][] の様に記述します。

もちろん、
int a[2][2] の様に記述しても構いませんし、
int* a[2] でも大丈夫だと思います^^;

記憶の中のものなので、実際試してみてください^^;
  • 回答No.4

int* a[2] は駄目だけど, int (*a)[2] なら OK (もちろん int a[][2] でも OK) int型の大きさ 2の配列 2個からなる二重配列 x[2][2] の配列名 xを単独で書いた時の型は int** 型ではなく, int (*)[2] または int a[][2] 型 なのでこう書かなければいけない. int** はint型の値を指すポインタのポイン ...続きを読む
int* a[2] は駄目だけど,
int (*a)[2] なら OK (もちろん int a[][2] でも OK)

int型の大きさ 2の配列 2個からなる二重配列 x[2][2]
の配列名 xを単独で書いた時の型は int** 型ではなく,
int (*)[2] または int a[][2] 型
なのでこう書かなければいけない.

int** はint型の値を指すポインタのポインタの型,
int(*)[n] はint型の値をn個並べた配列へのポインタの型,
で両者は全く異なる型である.

ついでに,main の返却値は void でなく int が正しいと思います。
このQ&Aで解決しましたか?
-PR-
-PR-
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


いま みんなが気になるQ&A

-PR-

ピックアップ

-PR-
ページ先頭へ