非常に大きな配列を宣言したかったのです。配列の最大サイズは size_t であり、UINT_MAX として定義されていることがわかりました
だから私はこのようなコードを書いた
int arr[UINT_MAX];
これをコンパイルすると、配列次元のオーバーフローと表示されます
しかし、私がこのように書くとき
size_t s = UINT_MAX;
int arr[s];
正しくコンパイルされます。違いは何ですか
最初のエラー:size_t
は必ずしもではないため、その最大値は( )unsigned int
のものとは異なる場合があります。さらに、C++ では、型の制限に関する情報を取得するために使用する必要があります。unsigned int
UINT_MAX
std::numeric_limits
#include <limits>
size_t s=std::numeric_limits<size_t>::max();
2 番目のエラー: これほど大きな配列を取得することはありません。はsize_t
任意のオブジェクトの最大サイズを表現できる必要があるため、アプリケーションで使用可能なアドレス空間全体として大きなオブジェクトを表現するのに十分な大きさである必要がありますが、そのような大きなオブジェクトを割り当てようとすると、アドレス全体を専用にする必要があります実行不可能なスペース。int
さらに、その大きさの s の配列を要求しています。つまり、サイズがUINT_MAX*sizeof(int)
バイトになることを意味します。これは、おそらくアドレス空間全体の約 4 倍になるでしょう - 明らかにナンセンスです - ちなみにsizeof(arr)
、サイズを表現することはできません一般に、ポインターはその配列の先頭に到達することさえできませんでした。コンパイラはこれらの障害を検出し、それを停止します。
さらに、スタックにそのことを割り当てようとしていると推測します。通常、アプリケーションが使用できるすべてのメモリよりもはるかに小さいため、大きな配列をそこに割り当てることはお勧めできません (使用する必要があります)。そのためのヒープ)。
3 番目のエラー: すべてのメモリを割り当てることは意味がありません。大きなメモリ要件がある場合は、スタックではなくヒープに割り当て、OS や他のアプリケーションとうまく連携するために必要なメモリだけを割り当てる必要があります (この最後の考慮事項は、作業している場合には当てはまりません)実行中の唯一のアプリケーションである組み込みシステムの場合)。
C++ の 2 番目のスニペットは、VLA (C99 で使用可能ですが、現在および次の C++ 標準から強く拒否されているため) になるため、そのものがスタックに割り当てられている場合、非標準になるため、機能しないはずです。 . ただし、その場合、その配列を割り当てるコードは実行時に使用されます (一般に VLA は次元が固定されていません)。 VLAセマンティックが通常の配列と変わらない場合、オプティマイザーはVLAを最適化して通常の配列を作成しようとする可能性があります=>これは私が述べたのと同じ理由で失敗します)。
簡単に言うと、特にスタック上で、そのすべてのメモリ (アドレス指定することさえできなかった) を割り当てることは意味がありません。ヒープを使用して、必要なものだけを割り当てます。特別な要件がある場合は、OS が提供する特別な仮想メモリ機能を調べる必要があります。
エラーを遅らせています。
どちらの場合も約 16GB* の連続したメモリが必要ですが、これは 32 ビット マシンでは不可能です。
あなたの最初の試みはサイズをハードコーディングすることであり、あなたのコンパイラはそれが成功しないことを事前に教えてくれました。
2 番目の試行では、コンパイラの警告をバイパスしたサイズの変数を使用していますが、プログラムを実行しようとすると失敗します。
*典型的なアーキテクチャについて
size_t s = UINT_MAX;
int arr[s];
s を const として宣言しないとコンパイルされません。また、UINT_MAX が配列の潜在的に最大のサイズであることに注意してください。実際には、数百万を超えるサイズの配列を宣言することはできません。これは、静的および自動であり、メモリが限られているためです
size_t s = UINT_MAX;
int arr[s];
arr が可変長配列 (VLA) であることを意味します。C++ 標準では許可されていないと思います。でコンパイルすると警告が表示されると思います
g++ -ansi -pedantic -std=c++98
また、考えてみてください。バイト数がarr
必要です。UINT_MAX * sizeof( int )
それはかなり大きいです!
どのコンパイラを使用していますか? VC++ では、両方のケースでエラーが発生します ( s
be に修正した後const
)。UINT_MAX * sizeof(int)
コンパイルされたとしても、プロセスのアドレス空間に確実に収まらないため、未定義の動作が発生し、さらに整数値自体がオーバーフローして、サイズの値が正しくなくなります。