• ベストアンサー

多次元配列のメモリ確保について

mallocを使ってA[500][40][40]のような多次元配列を動的に確保したいのですがどのように宣言すればよいでしょうか? 初歩的な質問で申し訳ありませんがおねがいします。

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

  • ベストアンサー
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.2

> 多次元配列を動的に確保したい 厳密には、いわゆる多次元配列を動的に確保することはできないと思います。 メモリのかたまりを動的に確保して、それをあたかも 配列であるかのごとく扱えるにすぎないのだと思います。 下記の例は、たぶんうまく動くと思います。 #include <stdio.h> #include <stdlib.h> #define X (2) #define Y (3) #define Z (4) int main(void) { int ***p, i, j, k; p = malloc(sizeof(int **) * X); if (!p) fprintf(stderr, "error\n"), exit(1); for (i = 0; i < X; i++) { p[i] = malloc(sizeof(int *) * Y); if (!p[i]) fprintf(stderr, "error\n"), exit(1); for (j = 0; j < Y; j++) { p[i][j] = malloc(sizeof(int) * Z); if (!p[i][j]) fprintf(stderr, "error\n"), exit(1); for (k = 0; k < Z; k++) { p[i][j][k] = i * 100 + j * 10 + k; printf("p[%d][%d][%d]=%d\n", i, j, k, p[i][j][k]); } } } return 0; }

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (5)

回答No.6

過信しないでください。参考程度に。 /*データ*/ struct Handle3DArray { int xMax; int yMax; int zMax; int* pMemory; }; /*一次元に変換*/ int CalcIndex(const Handle3DArray* p, int x, int y, int z) { const int lay = p->xMax * p->yMax * z; const int vol = x + p->xMax * y; return lay + vol; } /*体積*/ int CalcSize(const Handle3DArray* p) { return (p->xMax * p->yMax * p->zMax); } /*確保*/ void Alloc(Handle3DArray* p) { p->pMemory = (int*)malloc(sizeof(int) * CalcSize(p)); } /*開放*/ void Dealloc(Handle3DArray* p) { free(p->pMemory); memset(p, 0, sizeof(Handle3DArray)); } /*値を入れる*/ void Set(Handle3DArray* p, int x, int y, int z, int iValue) { p->pMemory[CalcIndex(p, x, y, z)] = iValue; } /*値をとる*/ int Get(const Handle3DArray* p, int x, int y, int z) { return p->pMemory[CalcIndex(p, x, y, z)]; } /*お試し*/ void main() { // x, y, z Handle3DArray a = {500, 40, 40, NULL}; Alloc(&a); int iTest = 0; for(int x = 0; x < a.xMax; ++x) for(int y = 0; y < a.yMax; ++y) for(int z = 0; z < a.zMax; ++z) { Set(&a, x, y, z, iTest++); const int res = Get(&a, x, y, z); printf("%d\n", res); } Dealloc(&a); }

stickright
質問者

お礼

参考になるソースを送っていただきありがとうございます。 プログラミングスキルがまだまだ足りなくてアロー演算子などが 苦手ですが、これからの参考になりそうなので読ませていただきます。

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.5

> 処理系によってできたりできなかったりします。 > 例:gccではできる、Borland C++ではできない Borland C++ Compilerは古い規格に従っているからです。 処理系が書かれていないので、Cの現行規格で使える方法を紹介しました。

stickright
質問者

お礼

ありがとうございます。 私の使っているのはVC++ 6.0なのですが、できなかったようです。

全文を見る
すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.4

>#3さん 処理系によってできたりできなかったりします。 例:gccではできる、Borland C++ではできない

stickright
質問者

お礼

細かく説明していただきありがとうございます。 先程の方法で試してみようと思います。

全文を見る
すると、全ての回答が全文表示されます。
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

こんな感じでしょうか? int (*A)[40][40] = malloc(sizeof(int[500][40][40])); 各要素数は可変にすることも可能です。 int a = 500; int b = 40; int c = 40; int (*A)[b][c] = malloc(sizeof(int[a][b][c]));

全文を見る
すると、全ての回答が全文表示されます。
  • fifaile
  • ベストアンサー率25% (622/2403)
回答No.1

検索で最初に出てきたページですが、どうでしょう? http://sometime.minidns.net/~ccgi/pointer_array.html

stickright
質問者

お礼

ありがとうございます。 擬似的な多次元配列についてとても詳しく説明されており、メモリ確保できるようになりました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 2次元配列を確保したいのですが、

    2次元配列を確保したいのですが、 size of array 'buf' is too large というエラーで確保できません。 mallocを使って確保しようとしましたが、コンパイルできましたが、 実行するとメモリ確保に失敗します。 大きな2次元配列を確保する方法を教えてください。

  • アドレス格納のための二次元配列のメモリ動的確保

    アドレス格納のための二次元配列のメモリ動的確保 二次元配列のためにメモリを動的確保しなければならないのですが、 その配列に格納したいものが 「DATA型のポインタ」です。(DATA型はtypedefした構造体です。) プログラム実行中にmallocで確保した、数あるDATA型の構造体の、その先頭アドレスを リストアップするための配列です。 この場合、どのような形でmallocすればよいのでしょうか? 教えていただけるとありがたいです。よろしくお願いいたします。 -- たとえば m×n のint型の配列は、 ◆ int *i; ◆ i = (int *)malloc( m * n * sizeof(int) ); となりますよね。 この要領がでやるのが一般的にわかりやすいものだとするならその方法でやりたい (後発の人が自分のソースコードを読む可能性があるため)のです。 -- 同様にm×nの「DATA型のポインタを格納するための二次元配列」を動的確保したい場合、 ◆ DATA *d; ◆ d = (DATA *)malloc( m * n * sizeof(DATA) ); この文にどのように付け加えたら良いのでしょう? もうあと一歩な気がするのですが(笑)。しかし参考書等で勉強しましたがわかりませんでした・・・。 わかる方、どなたかよろしくお願いいたしますm(_ _)m あとこれだけ通ればコンパイルが通るんです!!!!! たぶん(笑)

  • 2次元配列の動的確保&配列の添え字の書式について

    (1)2次元配列の動的確保について 1次元配列の動的確保は理解できたのですが、次のプログラムの 文(ⅰ)~(ⅱ)の意味を理解できていないので教えてください。 int **a, j, k, nrows=3, ncolumns=4 ; a = (int **)malloc(nrows * sizeof(int *)); a[0] = (int *)malloc(nrows * ncolumns * sizeof(int)); …(ⅰ) //先頭アドレスに… for(j = 1; j < nrows; j++) a[j] = a[0] + j * ncolumns; …(ⅱ)   //この行が特にわかりません。 (2)配列の添え字について この書き方はどういう意味になりますか? out[X_SIZE * (i) + (j)] 分かる方、回答お願いします。

  • 2次元配列の動的確保について、アドバイス下さい

    今、大容量の2次元配列を造りたいので、 メモリの動的確保の勉強をしてました。 昔は、サイズ分mallocで確保して、配列の各行の先頭アドレスを それぞれ対応させていって、行列としてポインタを扱えるようにしてたのですが、 調べていると、もっと簡単に2次元配列のメモリを確保できるみたいなので、その方法を調べていました。 その中で、 if(!(ptr = (int (*)[RETSU])calloc(GYOU*RETSU, sizeof(int)))) こういう例題を見つけたんですけど、 これの、(*)[RETSU])のところが、理解できません。 これは何をしているのでしょうか? どういう言葉で検索すれば、説明が出てくるのか解らなかったので質問させて頂きました。 この(*)[RETSU]の感じの書き方をすると、結構簡単にメモリ確保できるみたいなので、解説、または説明サイトなど教えて頂けると助かります。 または、例題を書いていただけるとスゴク助かります。 ちなみに私が造りたいのは、 100行300000列 ほどの配列です。 是非、よろしくお願いします。

  • 多次元配列の動的メモリ

    1次の配列aの動的メモリは例えば 「double *a;  int num = 3; //配列の数  a = new double [3];」 などとすれば確保できることは分かるのですが、 二次元配列など、多次元配列の動的メモリは どのようにすれば確保できるのですか?

  • 3次元配列

    初歩的な質問で申し訳ございません、非常に困っています 教えて下さい lotno(1~4,1~4,1~5) の3次元配列を宣言し、計算で求められた値を代入したいのですが どのように記述したらいいのでしょうか? また配列 lotno() はモジュール変数です

  • 2次元配列の動的確保について

    共分散行列を2次元配列に格納しようとしているのですが、 その要素は、左下半分と右上半分が同じになるため 対角要素と、どちらか半分だけを格納してメモリを節約したいと考えています。 以下のように動的確保することでメモリは節約できているでしょうか? if( (a = (double **)malloc(sizeof(double *) * (N) ))==NULL ){ fprintf(stderr, "error malloc for a\n"); exit(0); } for( i=0; i<NN; i++ ){ if( ( a[i] = (double *)malloc(sizeof(double) * (i+1) ))==NULL ){ fprintf(stderr, "error malloc for a\n"); exit(0); } } *節約しない場合は、i+1 が N になります。 確保できているのなら、どのように参照すればいいのでしょうか?データの並び(?)は、a[0][0],a[1][0],a[1][1],a[2][0],a[2][1],a[2][2],,,というように並んでいるでしょうか? 例えば、a[0][1]を参照しようとすると、シグメンテーションフォルトなど起こりうるでしょうか。必要であれば、上プログラム内Nは、3000程度と考えてください。 そして、もし他にメモリを節約する上で良い方法があれば、ご教授していただけたらと思います。 よろしくお願い致します。

  • 2次元配列の動的確保

    ある画像を読み込むため、その画像を格納できる幅、高さを持った配列を動的に確保しようと考えています。 幅をxsize、高さをysizeで次のように記述しました。 unsigned char **src; int i; src = (unsigned char**)malloc(sizeof(unsigned char*) * ysize); src[0] = (unsigned char*)malloc(sizeof(unsigned char) * xsize * ysize); for(i=1; i<ysize; i++) src[i] = (src[0] + i * xsize); わざわざポインタのポインタを使用したのは、動的に確保した配列を2次元的なアクセスをしたかったためです。 画像の読み込み時は fread(src[0], sizeof(unsigned char), xsize * ysize, fp); としています。 上に記述したソースは問題なく動作しました。 しかし、上の場合だと全ての配列を連続して確保することができません。つまりsrcでmallocを一回、src[0]でmallocを一回使っているため、ポインタの配列の直後に配列を確保する保障がありません。そこでいっぺんに確保することを考えました。 unsigned char **src; int i; src = (unsigned char **)malloc(sizeof(unsigned char *) * ysize + sizeof(unsigned char) * xsize * ysize); for(i=0; i<ysize; i++) src[i] = (unsigned char *)(src + sizeof(unsigned char *) * ysize + i * xsize); このように組み上げ、読み込み時は上のfreadと同様に記述したところエラーが出てしまいました。 やはり一行目のmallocで無理やりsizeof(unsigned char *) * ysize + sizeof(unsigned char) * xsize * ysize分確保するのは失敗だったのでしょうか?

  • ポインタ配列の動的確保

    ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #include<stdio.h> #include<stdlib.h> #define kensu 3 main() { char abc[kensu+1]={'A','B','C','\0'}; char *ptr[kensu]; int i; printf("3つの整数を入力して下さい。\n"); for(i=0;i<kensu;i++){ ptr[i]=(char*)malloc(sizeof(char)*10); if(ptr[i]==NULL){ printf("メモリの取得に失敗しました"); exit(1); } printf("整数%c:",abc[i]); fgets(ptr[i],10,stdin); if(ptr[i][strlen(ptr[i])-1]=='\n') ptr[i][strlen(ptr[i])-1]='\0'; } for(i=0;i<kensu;i++) free(ptr[i]); } ちゃんと動いているようです。 しかし、ポインタ配列の動的確保をネットで調べてみると、ポインタのポインタ(?)を使って、下記のように2度mallocしています。 #include <stdio.h> #include <stdlib.h> #define N 3 int main(void) { char** arr; int i,j; arr = (char**)malloc(N * sizeof(char*)); /* ポインタ配列を確保 */ /* 配列の要素それぞれにつき、メモリ領域を確保 */ for(i=0;i<N;i++) arr[i] = (char*)malloc(N * sizeof(char));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。

  • サイズがいろいろの2次元配列を数多く発生させる方法

    2次元配列は、すなわちマトリックスということになります。2次元配列を数多く発生させるために3次元配列が定義できると楽になります。しかし、2次元のマトリックスのサイズが異なる場合、どうなるでしょうか。 例えばA(i,j,k)ですが、i=1の場合、i=2の場合、....でj,kの取る範囲が異なるということなのですが。最大にとっておけばいい、ということにはなりますが、使わないメモリを確保することにちょっと抵抗があるのですが。言語はFortranなので難しい面があると思います。C言語だったらmallocを使うんだろうと思いますが。