こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

C言語 配列の長さの上限

C言語で配列Array[N]の長さNの上限っていくらなんでしょうか?
もし可能なのであれば上限を2147483647にしたいのですが、方法を教えてください。

投稿日時 - 2009-01-29 09:59:28

QNo.4670548

すぐに回答ほしいです

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

そもそもWindowsの32bit版はアプリが仮想メモリ空間を2GBしか使えません。2GBを超えるには64bit版が必要です。
たとえ64bit版OSだとしても添え字が2147483647って、単純なintの配列だとしても4x2147483647=8GB必要ですね。実メモリ16GBとかのPCを用意しますか?
そもそも配列で2147483647個必要なアルゴリズムに問題ありだと思います。

投稿日時 - 2009-01-29 10:51:30

お礼

8GBとはエラーが出るはずです。
ありがとうございました。

投稿日時 - 2009-01-30 01:04:21

ANo.2

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(7)

ANo.7

規格上、1個のオブジェクトのバイト数として保証されるのは...

C90の場合、32767バイトまで
C99の場合、65535バイトまで

です。
バイト数ですので、配列の要素がint型であれば、(C90なら)32767/sizeof(int)バイトまでです。

投稿日時 - 2009-01-29 12:57:24

ANo.6

(私の経験では)添え字の中は符号付のint型で解釈されるのでアクセスできるのはint型の正の最大値まで。
※添え字で参照できないだけで、ポインタ使ったり多次元配列とのUNIONにしたり工夫すれば使用は可能

他の方の回答にあるように、確保出来る配列サイズの最大は別問題

投稿日時 - 2009-01-29 12:27:12

ANo.5

あなたの環境が全く分からないので具体的な上限は書けませんが, 規格上ホステッド環境 (端的には「OS の上で動いている状態」) では「65536 バイト以上のオブジェクトは使えなくても文句は言えない」となっています. つまり, sizeof Array ≧ 65536 となるときには動かないかもしれません.
おまけですが「そもそもWindowsの32bit版はアプリが仮想メモリ空間を2GBしか使えません。2GBを超えるには64bit版が必要です。」というのは正確じゃないですね>#2.
仮想メモリ空間そのものはちゃんと 4GB とられています. ただしカーネルが使うメモリ分として 2GB (オプションを付ければ 1GB) 持っていかれるので, 「ユーザプログラムが自由に使える領域」として 2GB (または 3GB) の制限があります... という説明も本当は正確じゃない (1プロセスでそれを超えるメモリを使う技術は存在する) んだが, 面倒なので以下省略.
とはいえ, こんなことができるかどうかを考える前に, どうしてそんなにメモリが必要なのかを検討するべきだというこれまでの回答者の意見には全面的に賛成.

投稿日時 - 2009-01-29 11:57:28

ANo.4

>C言語で配列Array[N]の長さNの上限っていくらなんでしょうか?

言語仕様上では、上限はありません。

コンパイラは「実行時に実際にメモリが確保出来るかどうかは考えず、言われた通りに、言われた通りの領域を確保するようなプログラムコードを生成するだけ」です。

リンクして実行ファイルを作ろうとした時にサイズオーバーしてエラーになろうが、実行時にスタックやデータ領域が足りずに例外を発生して異常終了しようが、コンパイラは「お構いなし」です。

ただ黙々と「言われた通りにコード生成」して「後の事は知ったこっちゃない」のが「コンパイラ」です。

そして「後の事は知ったこっちゃない状態」で作られたプログラムは、実行したとたん「メモリが破綻して異常終了」するでしょう。

>もし可能なのであれば上限を2147483647にしたいのですが

それは「要素数が2147483647個の配列を作りたい」って事ですか?

だとしたら「その配列が確保出来る実行環境」を用意し、そこで実行すれば良いだけです。

例えば「64ビットCPUを搭載し、64ビットのアドレス空間すべてにメモリを実装してあって、64ビットのアドレス空間を自在に使用可能なOSを走らせ、そのOSで動く実行ファイルを生成するコンパイラ」を使えば、要素数が2147483647個の配列を何個でも使えます。

なぜなら、その動作環境では「メモリが18446744073709551616バイトもある」のですから「要素数が2147483647個の配列なんか、ゴミみたいなもん」です。

このように「実行環境で、メモリが無尽蔵にある」かも知れないので「コンパイラは、言語仕様上では、配列の要素数に上限を設けていない」のです。

下手に、仕様に「上限」を定めてしまうと「実行環境では充分なメモリがあるのに、言語の仕様に縛られて、大きな配列を確保出来なくなってしまう」という弊害が出ます。なので「仕様では、上限無し」になっています。

もちろん、それは「仕様の上だけ」であって「実行時、実際に、そんだけのメモリが確保出来るかは、まったく別の問題」です。

投稿日時 - 2009-01-29 11:12:53

ANo.3

私が今ままで、プログラミングをしてきた経験では、
そのような、非常に大きい添え字を必要とする状況は発生しませんでした。
通常、そこまでの添え字を必要としないと思いますが、
どうしてそのようなことをなさりたいのでしょうか?
そのこと自体に、非常に興味があります。
よろしければ、その理由もしくは背景を教えていただけませんでしょうか?

投稿日時 - 2009-01-29 10:57:51

補足

物理系のシミュレーションをしています。
試行ごとにある現象が起こるかどうかをrand()%RAND_MAXがその現象が起こる確率pに比べて大きいか小さいかで判断しています。
この方法では毎回rand()を参照しなければならずボトルネックになっていました。そこで、あらかじめArray[0]~Array[RAND_MAX-1]まで乱数を読み込んでおいて順番に使おうかなと考えました。
そのためにArray[RAND_MAX] (RAND_MAX=2147483647)の配列を準備したかったというのが背景です。
しかし、先ほど自分でもいろいろと調べていたらxorshift()という関数が非常に高速でかつ乱数としても優れているそうなのでそちらを使ってみることにしました。xorshift()に関しては分からないことがありますが、それは別の質問とします。

投稿日時 - 2009-01-30 00:57:18

ANo.1

言語上の上限はsize_tの上限と一致するとは思いますが、そんなメモリをスタックに保有できるような環境は存在しません。
Windows上では一般的にスタックは1Mとかですから、実質的にはその半分の500kも確保できれば良いほうじゃないんでしょうか?
C言語で長大な配列を確保したい場合は、動的配列にするのが常套手段ですが、それでも2Gなんて連続領域を確保することはほぼ不可能だと思います。

投稿日時 - 2009-01-29 10:20:26

あなたにオススメの質問