C言語の記憶領域
動機
現在、大規模数値計算プログラムをC言語で書いており非常に大きな配列を使うのだが、記憶領域(下記のようなコードの書き方)によって配列にどのような違いが出てくるのか気になったため、色々調べてみた。
/* 配列の宣言方法 */
/* 1.ローカル変数的な配列 */
int array[5];
/* 2.static変数的な配列 */
static int array[5];
/* 3.ポインタ変数的な配列(動的確保) */
int *pntr;
int num_elements;
printf("配列のサイズを入力:");
scanf("%d", &num_elemtns);
array = calloc(num_elements, sizeof(int));
4つ(5つ)の記憶領域
メモリは大きく4つの領域に分けられる。1番の方が低位のアドレスで、4番の方が高位のアドレスである。
1.テキスト領域
プログラムのコードが保存されるメモリ領域。
2.静的領域
グローバル変数や静的変数が保存されるメモリ領域。
上記の配列の宣言例での2番に該当。
3.ヒープ領域
malloc系でプログラム実行中に確保できるメモリ領域。
上記の配列の宣言例での3番に該当。
4.スタック領域
ローカル変数などが保存されるメモリ領域。
上記の配列の宣言例での1番に該当。
ローカル変数の保存されるスタック領域は数MB程度のメモリしか持ち合わせていないので、それ以上のサイズの配列を使う際には配列をヒープ領域、もしくは静的領域に保存してあげる必要がある。ちなみに、参考サイトによると、どちらを使った場合も処理速度に大きな変化はないらしい。
さらに詳しく分けることもできるらしいが、今回は省略する。
詳しくは以下のサイトを参考
静的と動的
静的
プログラムコンパイル時に決定されるもの。
ローカル変数やstatic変数は静的変数であり、あらかじめ決めたサイズしか持たず、必要なサイズがわかっている時にはこちらでも問題ない。
動的
プログラム実行時に決定されるもの。
ポインタ型の配列は動的であり、プログラム実行中にそのサイズを決定することができ、必要なサイズが不明なときでも対応できる柔軟性をもつ。
結論
少なくとも最初にあげた3種類の配列の宣言方法は、メモリの大きさという観点から2つに分けられる。数MB以下程度の比較的小さい配列を扱う場合はローカル変数としてスタック領域に保存されても問題ないが、数値計算など非常に大きな配列を扱う場合は、静的領域やヒープ領域に保存するべきある。
疑問
- static宣言時の配列と、ポインタ変数型の配列は、どちらも数MB以上の配列を扱うことができるらしいが、どちらの方がメモリ容量的には大きいのだろうか?また、どちらの方が数値計算には適しているのだろうか?
というのも、先日static宣言で配列を使おうとしたがエラーが出た。詳しい内容は今手元にないので、今度記述しておくが、両者の間に動的、静的以外の違うがあるかどうかも確認しておきたい。
参考サイト