• ベストアンサー

C言語の2次元配列 容量が大きすぎる場合の対処方法

私はC言語をもちいて2次元配列を作ろうとしています。 しかし、配列数が double c[10000][10000]; と大きいものにすると、エラーになってしまいます。 もちろん小さい double c[10][10]; のような配列では問題ありません。 malloc関数とかも調べたのですがなかなかいい文献が見つからずに 困っています。 どうかいいご意見があればよろしくお願いします。

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

  • ベストアンサー
  • usatan2
  • ベストアンサー率37% (163/436)
回答No.7

No.5です。 >今はa[],b[]に10000個の配列があります。これをc[a][b]に格納するためにどうするか、例文を書いていただいてもよろしいでしょうか? 例文ではありませんが、感じだけ書きましたので参考にしてください。 パラメタの順序や型は正しくないと思いますので、各関数はよく調べて使ってください。あくまで、こんな感じ、ということです。 ------------------- #include <stdio.h> #include <io.h> double read_c(FILE *fp, int x, int y) {  double c;  fseek(fp,(x*10000+y)*8L, SEEK_SET);  fread(&c, 1,8, fp);  return c; } void write_c(FILE *fp, double *c, int x, int y) {  fseek(fp,(x*10000+y)*8L, SEEK_SET);  fwrite(c, 1,8, fp); } int main(void) {  FILE *fp;  double c,s;  int x,y;  int a[10000],b[10000];    fp = fopen("c.dat","w+b"); // double c[10000][10000]; の意味    for(x=0; x<10000; x++) {   for(y=0; y<10000; y++) {    c=a[x]*b[y];    write_c(fp, &c, x,y); // c[x][y]=a[x]*b[y]; の意味   }  }    for(x=0; x<10000; x++) {   s=0;   for(y=0; y<10000; y++) {    s += read_c(fp, x,y); // s += c[x][y]; の意味   }   b[x] = s / 10000;  }    fclose(fp);  return 0; }

dom-dom
質問者

お礼

くわしい説明本当にありがとうございました。 図々しい質問でしたがお答えいただいて本当に感謝しています。

その他の回答 (6)

  • usatan2
  • ベストアンサー率37% (163/436)
回答No.6

No.5です。 >ご回答ありがとうございます。あまりくわしくないのでdatというものが何なのかよくわかりません。 これは、私の「そのデータを記録するファイルc.dat を作ります」に対する反応ですね。ファイル名ですから適当です。拡張子は気にしないでください。c.abcでもa.bcdでも、「double_c10000_10000のデータを保存するファイル.tmp」というファイル名でも何でもよいです。私が勝手に、Cという配列のデータを保存するファイルという意味でc.datという名前をつけただけです。 アイデアは単純で、「巨大なデータdouble c[10000][10000];をファイル上に確保する」というだけです。mallocでメモリ上にデータの保存先を確保する代わりに、ファイル上に確保するわけです。 ファイル名は何でもいいです。本質ではありません。

dom-dom
質問者

お礼

ご返答ありがとうございます。 現在も問題に取り組んでいます。 今はa[],b[]に10000個の配列があります。これをc[a][b]に格納するためにどうするか、例文を書いていただいてもよろしいでしょうか? 大変恐縮ですが、していただけると非常に助かる限りです。 ずうずうしいお願いをして申し訳ございません。

  • usatan2
  • ベストアンサー率37% (163/436)
回答No.5

巨大データをファイルにしたら、遅いですがエラーにならないと思います。つまり、 double c[10000][10000];の代わりにそのデータを記録するファイルc.dat を作ります。 そして、c[x][y]にアクセスする場合、lseek(fd,(x*10000+y)*8, SEEK_SET);して、fread()やfwrite()で読み書きすればよいでしょう。変数がchar なら*8は省略、変数double が8バイトでなく16バイトなら *16です。これは昔、DOSプログラムで巨大データを操作する場合使ったテクニックです。

dom-dom
質問者

お礼

ご回答ありがとうございます。あまりくわしくないのでdatというものが何なのかよくわかりません。 もういちど勉強してみます。

noname#144013
noname#144013
回答No.4

dom-domさん、こんにちは。 まずは、他の回答者の方も仰っているように、そもそも、なんでそんな巨大なサイズの 配列がいるのか?本当に必要なのか?どうかをじっくり検討してみた方が良いかもしれ ません。 プログラムの処理内容は判りませんが、一度に(同じタイミングで)その配列全体をアク セスする必要があるのかどうか..... 一度にアクセスする範囲が限定できるなら、配列を小さくして必要な部分のデータだけ 格納するような方法が採れると思います。 ※配列のサイズを大きく取りすぎるのは、メモリが勿体無いのもありますが、トラブルの 原因にもなりやすいのであまりオススメできません。 dom-domさんが望まれる回答でなくてすみませんでした。m(__)m

dom-dom
質問者

お礼

ありがとうございます。 確かに大きすぎるので、もっと上手いやり方が存在するかもしれません。 配列を小さくすることも検討して試してみます。

  • salsberry
  • ベストアンサー率69% (495/711)
回答No.3

「エラーになってしまいます」というのが、どんなエラーなのか、コンパイル時なのか実行時なのかなどをまずははっきりさせましょう。あと、OSとコンパイラの名前とバージョンも。 自動変数ならば、800MBも確保できないのが普通でしょうね。 他の方も書いているとおり、やはりmallocなどの方法で確保するのが基本です。ただし、2次元配列ということなので、1次元の場合と比べてアクセスは少々面倒になります。 要素数 M×N のdouble型の領域を確保して、i行j列の要素にアクセスする (0≦i<M, 0≦j<N) には、下記のようにします。 double *p = (double *)malloc(sizeof(double) * M * N); if (!p) { エラー処理 } ... p[i*N + j] = 0.0; ... free(p); p[i][j]とは書けないことに気をつけてください。 なお、mallocが失敗するようなら、根本的にメモリが足りません。物理的にメモリを増やすか、もっと少ない要素数で演算できるようにプログラムを変えてください。

dom-dom
質問者

お礼

ご意見ありがとうございます。 cはあまり知らないのでおそらくmallocというのをいろいろ調べたのですが正しく理解できず使いこなせないだけだと思います。 またソースの例まで書いてくれてありがとうございます。 salsberryさんの例を参考にしてもう少し試してみます。

  • TT414
  • ベストアンサー率18% (72/384)
回答No.2

auto変数の場合スタックサイズにより制限されます(1MBの物が多いです)。 auto変数でない場合はエラーにならない場合もあります。 auto変数の場合はスタックサイズを大きくするか、プログラムを変更して配列サイズを小さくしてください。

dom-dom
質問者

お礼

ご意見ありがとうございます 頑張ります

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.1

mallocで10000×10000×8バイト文の領域が確保できれば double c[10000][10000]; と同じサイズの領域を定義したことになります。 800MBなので、OKかどうかは環境によるかと思いますが。

dom-dom
質問者

お礼

やはり領域なんですね。ご意見ありがとうございます 頑張ります

関連するQ&A

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

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

  • 【C言語を教えてください!】2次元配列について

    【C言語を教えてください!】2次元配列について 2次元配列を用いて、コンソール画面(ターミナル)の中央付近に*を表示させるプログラムを作りたいのですがさっぱり分かりません。 画面の大きさは半角で横80 縦25です。 25は奇数ですので40×12に表示したいと思います。 2重ループでなら出来たのですが配列でのやり方がわかりません。 #include<stdio.h> main() { int i,j; for(i=0;i<25;i++){ for(j=0;j<80;j++){ if(i==12&j==39){ putchar('*'); }else{ putchar(' '); } } } return 0; } 回答お願いします!

  • 多次元の配列を[ ]で括って見やすくトレースするには?

    多次元の配列を[ ]で括って見やすくトレースするには? 何次元か特定される配列ならばforなどで次元の数だけ繰り返せばできるとは思うのですが そうでないときにも [ [ [a,b,c,...],[],[],...],[],[],... ] のように隣り合う要素(配列)との切れ目が見やすいようにトレースする方法はありますか? プログラムには影響しませんが、トレースすると1次元の配列と同じように , だけで区切られてトレースされてしまい見にくいですので 配列が何次元か返させる関数など書ければ良いと思うのですが FlashPlayer10、ActionScript3.0です 質問の意味理解していただけるでしょうか お願いします

    • ベストアンサー
    • Flash
  • 多次元配列の動的メモリ

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

  • Functionの戻り値を2次元配列にする方法

    VB.NETを使いはじめた初心者です。 Functionの戻り値を2次元配列にして データを取得したいのですが、 「Doubleの1次元配列はDoubleから派生していないためDoubleの1次元配列の1次元配列の値をDoubleの2次元配列に変換できません」とエラーがでます。 どのように変更すればよいでしょうか。 ご教授願います。 Function f1 As Double()() Dim temp(2,3) As Double ・・・・・ Return temp End Function

  • C言語 配列を交えた関数

    C言語にて配列を絡めた関数を作っています 配列には後にそれぞれの値を与えるのですが double total(int n){ int i; double total = 0; int y[NUMBER] ={0}; for (i = 0 ; i < n ; i++) { tota = tota + (combination(n,i) * power(i) * y[n - i]);} return (tota); } combinationは順列nCi powerは-1^iを表してあり 別々に表示させた場合問題なく出力されます printf("%lf\n" , res + combination(1,0) * power(0) * y[1] + combination(1,1) \ * power(1) * y[0] のようにして実行した場合もただしくでます しかしこれだとtotalを出力させたとき0となり(関数内で配列を初期化させているため?)={0}を消すと出力時に恐ろしい桁の数になってしまいます この関数をうまく作動させるための改善案をご指導願えませんか?情報不足で判断できない場合補足にて追加させていただきます 当方C言語初心者のため詳しくお願いいたします

  • c言語 配列

    関数の中で複数の値を配列で返したいのですが,どうすればいいでしょう? 配列を関数に渡す時にはアドレスが渡されるので,ポインタと同様関数内で値を変えればmain関数の値も変わるのではないかと思ったのですが,上手くいきません. 知りたいのは,main関数の中の配列(できれば2次元配列)の値を他の関数から値を変更する方法です.下のプログラムはためしに書いてみたものです.質問を理解するうえで役立てば幸いです. #include<stdio.h> void func(double aaa[][3] ,double bbb[]); void main(void){ double array_a[3][3]={{1,2,3},{4,5,6},{7,8,9}}; double array_b[3]={0}; func(array_a,array_b); } void func(double aaa[][3] ,double bbb[]) { int i,j; for (i=0;i<3;i++) { for (j=0;j<3;j++) { bbb[i]=bbb[i]+aaa[i][j]; } } }

  • 二次元配列が、勝手に一次元配列になってしまう

    Excelのマクロで、二次元配列を格納したバリアント型を戻り値とする関数を作ったのですが、… 二次元型配列のひとつの要素数が1の時、受け取ったバリアント型変数は、一次元配列になっています。 列ベクトルなら、それもありかな~と思うのですが、なんで、行ベクトルまで、一次元配列にするんだよ~って、困っています。 シートから関数を呼んだ場合は、列ベクトルは列ベクトル、行ベクトルは行ベクトルとして、表示されるので、マクロの中で関数を呼び出した場合も、行列の情報を保持できる方法があるんじゃないかと思ったのですが。 どなたか、ご教示頂けるとありがたいです。 よろしくお願いします。

  • c言語のmalloc関数、またrealloc関数

    c言語のmalloc関数は確保するメモリの領域を、配列としてのみしか処理出来ないのですか。 つまり、malloc関数で確保したメモリの領域を変数、また多次元配列、また構造体としては処理出来ないのでしょうか。 c言語のrealloc関数は以前の確保したメモリの領域から、確保し直したメモリの領域の場所が変わるかもしれないという事ですが、この場合の場所が変わるという意味は、メモリの領域のアドレスが変わるという事でしょうか。 また、以前の確保したメモリの領域に代入していたデータが使用出来なくなるという事でしょうか。

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

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

専門家に質問してみよう