• ベストアンサー

多次元配列のポインタ渡し

C++を使用しています。 多次元配列を関数の引数として渡したいとき、関数側では void A::Func(int a[10][20][30])~ 呼びだし側では Finc(a); とやればいいのはわかります。 お聞きしたいのは、仮引数として呼び出された配列(上でいうa)をクラスのメンバ変数として保持したい場合の方法です。 aは先頭アドレスなのでそこを差すポインタを受ければいい、っていうことはわかりますが、 この方法ですと、受けたメンバ変数が配列みたいに[]を使ってアクセスできません。 (メンバ変数のポインタは配列じゃないから当然ですよね) これを通常の配列みたいに扱えるようにするにはどうしたらいいでしょうか。

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

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

class A {  int (*p)[20][30]; public:  void Func(int a[10][20][30)  {   p = a;  } };

Untitled1983
質問者

お礼

ありがとうございます。 うまくできました。

その他の回答 (2)

  • smat7
  • ベストアンサー率46% (7/15)
回答No.3

多次元の配列の場合、高次の添え字はその次元以下の配列要素数文のインクリメント量をあらわします。なので配列の先頭アドレスを渡しただけでは[]による参照ができません。これはそのポインタがどのような構成の配列であるかを関数プロトタイプ宣言時に明示することで解決できます。この時最低次元の要素数(例では10)は省略することはできますが、高次の要素数はコンパイル時に定数として固定されていなければなりません。これはaの要素を参照するために a[i][j][k] = *(a+(20*30*k+30*j+i))という計算をコンパイラがしなければならないからです

Untitled1983
質問者

お礼

ありがとうございます。 参考になりました。

  • ency
  • ベストアンサー率39% (93/238)
回答No.2

実際に試してみましたか? No1 jactaさんの方法で A::p[i][j][k] として何も問題ありませんよ。 たとえば、 void func( int *p_hoge ) { // *(p_hoge + i) だけでなく p_hoge[i] とすることも可能 } というのは問題ありませんよね? 要するに、これと同じことです。

Untitled1983
質問者

お礼

ありがとうございます。 その方法では1次元ではうまくいきますが、2次元以上では型変換に失敗し、コンパイルエラーとなりました。

関連するQ&A

  • 2次元配列とポインタの引数受け渡しについて

    2次元配列を関数に渡すときは、引数に渡す2次元配列と同じサイズを指定、もしくは2次元目のサイズのみ合わせて渡す方法がありますが、両方とも違うサイズで同じ関数を使いたいです。 最初は中身が同じで引数で受け取る2次元配列のサイズだけ、それぞれに合わせた引数を持つ関数を2つ作っていたのですが、なんだか冗長な気がしました。 そこで、2次元配列の先頭ポインタとサイズを受け取るようにすればいいのかと思い、テストとして次のプログラムを作成してみました。 #include <stdio.h> void func(unsigned char *a, int y, int x); int main(void) { unsigned char a[10][10]; func(a, 10, 10); printf("%d\n", a[7][4]); return 0; } void func(unsigned char *a, int y, int x) { int i, j; for (i = 0; i < y; i++) { for (j = 0; j < x; j++) { *(a + i*y + j) = i * j; } } } もちろんこれでも動くのですが、やはりこういう書き方はルールにはないので、コンパイルで警告が出ます。 a.c: In function ‘main’: a.c:10: warning: passing argument 1 of ‘func’ from incompatible pointer type a.c:4: note: expected ‘unsigned char *’ but argument is of type ‘unsigned char (*)[10]’ このような書き方はやはりやめたいいのでしょうか。 また、その際はサイズ別に関数を作るしかないのでしょうか。 他にいい方法があれば教えていただけると助かります。

  • 多次元配列とポインタ渡しについて

    多次元配列のポインタ渡しについて,自分で検索したのですがあまりにも様々で具体的な記述が無く質問させていただきました. 検索力不足もあるのでソースの提示だけでも結構ですので,ご回答お願いいたします. OS:Windows XP ソフト:VisualStudio.net2003(C++) C++プログラミング暦2ヶ月弱です. データを変換して多次元配列にデータを入れる自作の関数をつくりたいと考えています. 具体的には,a1からa2,b1からb2を10区間に分けてたデータを配列にしたいといったものです. 自分で記述した関数は以下の通りです. void Convert(float a1,float a2,float b1,float b2,unsigned short *Data){ int k; float a; float b; for(k=0;k<11;k++){ a = a1 + (a2 - a1) / 10; b = b1 + (b2 - b1) / 10; Data[k][1] = ( powf(2.0,16) * (a + 10.0) / 20; Data[k][1] = ( powf(2.0,16) * (b + 10.0) / 20; } } void main(){ float a = 10; float b = 20; unsigned short Data[11][2]; Convert(a1,a2,b1,b2,Data); ... } としています. ここでコンパイルすると, "5番目の引数をunsigned shortからunsigned short *に変換できません" となってしまいます. 配列の名前のみの部分はその配列の先頭アドレスを示すポインタであることから,自分では間違いがないと思っているのですが….

  • ポインタと二次元配列

    二次元配列a[ ][ ]の第1行の要素以後を0にするプログラムで動きます。 疑問なんですが、4行目のa[ ][4]は、なぜ[ ]のように空欄になっているんでしょうか。 また、8行目のpa=a[1];は、なぜpa=a[0];ではだめなんでしょうか。第1行は先頭行で0行目を意味しているのではないでしょうか。 #include <stdio.h> void main(void) /*ポインタと二次元配列*/ { static int a[ ][4]={{1,2,3,0}, {4,5,6,0}, {7,8,9,-999}}; int j,k,*pa; pa=a[1]; while(*pa!=-999){ *pa=0; pa++; } for(j=0;j<3;j++){ for(k=0;k<4;k++) printf("%5d",a[j][k]); printf("\n"); } }

  • ポインタによる関数への配列渡し

    林晴比古さんの「新C言語入門」でC言語を勉強している初心者です。 現在ポインタの勉強をしています。色々教科書の文例等をポインタで書くとどうなるか試しております。 上書P200練習問題2に「配列の最大値を返す(その際配列の長さを渡す)」プログラムがあり、それをポインタで渡すプログラムに直してみました。 仮引数に「maxdata」を設定し、そのアドレスを関数側に渡し、関数側ではポインタとして受け取る(そうすれば関数側からはreturnで値を返す必要がない)、と考え、下記のように書いてみました。 #include <stdio.h> void max_of_array(int n[], int len, int *ans); int main(void) { int dt[6] = {50,20,80,30,10,40}; int maxdata; max_of_array(dt,6,&maxdata); printf("最大値=%d\n", maxdata); return 0; } void max_of_array(int n[], int len, int *ans) { int i; ans = &n[0]; for (i=1; i<len; i++){ if (*ans < n[i]) *ans = n[i]; } } しかしコンパイルすると、何故か「最大値=1」となってしまいます。(正しくは80です) 他にも色々試してみましたがうまくいかず、かなり考えてみたのですがどうしても分かりません。お分かりの方、どうすれば正しくなるのが教えてください、よろしくお願いします。

  • 任意の要素数の二次元配列を渡したい

    関数で、各次元の要素を問わず、二次元配列を受け取りたいのですが、下記の方法では失敗しました (要素にアクセスすると落ちる) void func(void *p){ int **v=(int **)p } void func(int p[][3]) 上記のような、指定された数だけを受け取る方法をとるしかないのでしょうか ご存知の方が居ましたら教えてください

  • 2次元配列を引数とする関数について

    2次元配列を引数とする関数について 私は今、2次元配列を引数とする関数の表を作るという課題に取り組んでいます。 条件として、int a[数字][数字]={{1,2,3...}}という配列の宣言と同時の初期化は使わず、 関数内で表の値を代入し、値を表示する関数を作り、事実上二つの関数を作るというものです。 私は以下のようなプログラムを作り、動かしましたが、[数字][数字]=********のような本来 あるべき実行結果とは異なる数字の羅列が出てきてしまいました。 ↓ #include <stdio.h> void func(int a[][6]); void fund(int b[4][6]); void main(void) { int a[4][6]; fund(a); func(a); } void func(int a[][6]) { int i,j,b[4][6]; fund(b); for(i=0;i<4;i++)        { for(j=0;j<6;j++) { printf("a[%d][%d]=%d\n",i,j,a[i][j]); printf("\n"); } } } void fund(int b[4][6]) { int i,j; for(i=0;i<4;i++) { for(j=0;j<6;j++)          { scanf("b[%d]*[%d]=%d\n",&i,j,b[i][j]); } } } 本来の実行結果 1 2 3 4 5 6 2 4 6 8 10 12 3 6 9 12 15 18 4 8 12 16 20 24 紙にも書いて何回も見直しましたが、どこがおかしいのかわかりませんでした。 どうすれば良いのでしょうか? 何か良いアドバイスをよろしくお願いします。

  • 配列の受け渡しについて

    ある関数で、引数としてやりとりするデータが多いため、構造体にまとめて受け渡しするようにしています。 その構造体のメンバにポインタ変数を設け、2次元配列のポインタを受け渡しするようにしたいのですが、受け取った側でそのポインタを"2次元の配列"として扱うことができずに困っております。(2次元であることが認識できない?) 配列そのものを受け渡しする方法以外で、これを解決する手段はないでしょうか? (ANSI-Cです)

  • ポインタを使って構造体の配列を戻り値にするには

    関数の戻り値を構造体の配列(アドレスを受け渡しを利用して)にしたいのですがうまくゆきません。 以下のプログラムではコンパイルはできるのですが、 a0 = 2 a1 = 4198512 a2 = 4329332 と表示されてしまいa1,a2がうまくゆきません。 ********************************************* #include<stdio.h> struct test{ int a; }; struct test *func(void); void main(void) { struct test *data;//構造体ポインタ int i; data = func(); //ポインタにtest関数の戻り値(アドレス)を代入 for(i=0;i<=2;i++){   printf("a%d = %d\n",i,(data+i)->a); //構造体要素を表示 } } struct test *func(void) { struct test data[3]={1,2,3}; //構造体配列を定義 return (&data[0]); //構造体配列の先頭アドレスを返す } ************************************************* test関数から受ける取ったアドレス(&data[0])をポインタ(data)に代入して1づつずらして表示させれば a0=1,a1=2,a=3 となると思ったのですがどこが間違っているのでしょうか? よろしくお願いします。

  • mainの外に変数 vs ポインタ渡し

    C++についての質問です。プログラミング初心者ですが、よろしくお願いします。 最近、関数の外側でも変数を宣言できることを知りました。関数の外側で変数を宣言すると、全ての関数でその変数にアクセスすることができ大変便利なように思います。 「わざわざポインタ渡しなどする必要はないのでは?」と思ってしまいました。 これは何か問題があるのでしょうか? 初心者の言葉で説明しても理解しにくいかと思いますので、例として「足し算するプログラム」を以下に記載します。 ポインタ渡しで書くと、以下のような感じになるかと思います。 //●ポインタ渡し #include "stdafx.h" #include <iostream> void func(int x,int y,int *pans){ *pans = x+y; } void main(){ int a=10, b=20, ans; func(a,b,&ans); std::cout << ans << std::endl; } しかし、mainの外に変数を宣言すれば //●mainの外に変数 #include "stdafx.h" #include <iostream> int a,b,ans; void func(int x,int y){ ans = x+y; } void main(){ a=10; b=20; func(a,b); std::cout << ans << std::endl; } ansをポインタ渡しする必要なく、funcの計算結果をansに代入できました。 「●mainの外に変数」のプログラムはどのような問題や危険性を孕んでいるのでしょうか? 以上になります。長文お読みいただきありがとうございました。 よろしくお願いいたします。

  • 教えてポインタ

    例えば、以下のようなソース。 関数の中で、引数のポインタに値を入れてmainに戻す。 とても簡単なものです。 void func(int *N) {  *N=0; } main {  int  *N=1;  func(N);  printf("%d",*N) } 疑問は、ここからです。 (1)void func(int  *N) (2)void func(int*  N) (3)void func(int*  &N) 上記は、何が違いますか? なお、当方のVS2010で同じソースを作ると、 (1)の場合、エラーになります。(func関数の*N=0のところでダウン) (2)だと、OKになります。 (3)は、なに?

専門家に質問してみよう