C言語関係掲示板

過去ログ

No.37. 大きな配列の宣言


以前にも同じ質問をして、何度もすいません。原因はわかったようなのですが、どうしたらいいかわかりません。下のプログラムは配列a[m][n]に0から1の初期値をランダムに与えようとするプログラムです。このプログラムを実行するとアプリケーションエラーが出てしまいます。しかし、5行目の#define n 1000の部分を、100とかの小さい数字にするとちゃんと0から1の初期値を与えており、プログラムは正常に動いているようです。でも実際は、2000とか3000とかもっと大きい値を使いたいのです。どうしたらよいのでしょうか。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define m 1000
#define n 1000

void main(void)
{
srand((unsigned)time(NULL));
int i,j;
double a[m][n];
for (i=0;i<m;i++){
for (j=0;j<n;j++){
a[i][j]=(double)rand()/32767.0;
printf("%lf\t",a[i][j]);
}
}
}


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
int a, b;
double ans;

scanf("%d%d", &a, &b);
srand((unsigned)time(NULL));
ans = rand()/32767.0;
printf("%lf\t", ans);

return 0;
}

/*
1000 * 1000 の配列を作っていちいち"表示"するというのはどうでしょう。
どうせなら必要な部分だけ好きなときに計算する方が良いでしょう。
*/


こんにちは、ともじです。

yamaさんが作ったプログラムは配列を自動変数で宣言していますが、自動変数は
通常スタックエリアに確保されます。このスタックエリアは以外に小さく、大きな
配列を宣言するのには向きません。
ですので、大きな配列を使いたいのであれば、static宣言をし、静的エリアに
確保してみてください。
また、もし、大きさが可変なエリアなら、mallocで動的にエリアを確保した方が
いいと思います。

それにしてもdoubleで1000*1000は大きいですよね。エリアはshortで宣言し、
使うときに 32767.0 で割ってやると、1/4のエリアで済みますが、いかがでしょう。


>それにしてもdoubleで1000*1000は大きいですよね。

私の環境では、doubleは64ビットで表現されているので、
なにも考えずに単純計算で、8バイト×1000×1000だと仮定して
考えてみると実にこのa[][]の配列だけで8メガバイトのメモリを使用
していることになりますね。う〜ん凄い量だ!
確かにこのコードをコンパイルして走らせてみたら
stack dumpを含むエラーがOSから帰ってきたのでスタックが怪しいと
にらんでいたのですがやはり
「スタックに格納できる量にはある程度の制限がある」
のですね。勉強になりました。

私だったらたぶん、unsigned shortあたりで乱数を出してから、
最後に適当な数で割って小数点にするでしょう。
いわば「指数部ビット」の役割を自ら行うことにより負担を少なく・・・
と考えます。
それに浮動小数点での演算では、十分痛い目にあってるので・・・・。
もちろん、状況により・・・・が基本でしょうが。


shuさん、ともじさん、Toshi_2さん、いろいろ親切にありがとうございます。まだ初心者なので、わからないことがたくさんあるので、そのときはまたよろしくお願いします。本当にありがとうございました。

戻る


「初心者のためのポイント学習C言語」 Last modified:2001.8.8
Copyright(c) 2000-2002 TOMOJI All Rights Reserved