• ベストアンサー

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
質問者

お礼

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