LINUX-C成長の道(八):ストレージクラス、ダイナミックメモリ

3360 ワード

C言語にはいくつかのキーワードがあり、1つの変数または1つの関数を定義するときに、ストレージクラスキーワードと呼ばれるストレージ領域のタイプを指定します.
static,extern,register,auto
以下、一つ一つ説明します.
1,static
実はこのキーワードには、ストレージタイプだけでなく、3つの役割があります.次のコードを参照してください.
// 1. , 
static void func(void)
{
    static int n = 0; // 2.  , ( )
    printf("%d
", n); } static int global; // 3. ,
は、staticのC言語における3つの役割に気づき、そのうち1番目と3番目の役割は実際には同じであり、関数または変数の可視範囲を変更した.staticでローカル変数を修飾する場合にのみ、その役割はストレージ領域を表す.
2,extern
externキーワードは、識別子(変数または関数)の宣言を修飾するために使用され、識別子が「別の場所」で定義されていることを示します.次のコードを参照してください.
extern int a; //  “ ” , extern 
extern int f(); //  “ ” , extern 
「別の場所」とは、現在の位置にないことを意味し、別のファイルである可能性があり、そのファイルの他の場所である可能性がある.宣言が変数である場合、グローバル変数のみであり、ローカル変数はexternで宣言できません.
3,register
名前の通りregisterはレジスタに格納したい変数を修飾するために使用されますが、これはシステムに対する提案にすぎません.レジスタは希少なリソースであり、要求を満たすことができるかどうかはシステムの当時の状況次第です.しかし,システムが本当に変数をレジスタに格納するかどうかにかかわらず,プログラムはその変数をアドレス演算することができない.また、どの変数もregisterタイプとして定義できるわけではないが、レジスタの大きさはCPUのワード長に関係するため、一般的に32ビットシステムではレジスタも32ビットであるため、32ビット以下の変数をregister型と宣言することができる.
宣言ビットregisterタイプの変数は、一般に、最下位のオペレーティングシステムでは、ある変数を頻繁に読み書きし、この変数の読み書き速度がプログラムのパフォーマンスに直接影響し、プログラム全体のホットスポットでありボトルネックであるため、registerストレージ型と宣言する必要がある.
4,auto
autoというキーワードはsignedのように省略されるのが一般的です.autoの意味は、1つの変数を「自動」ストレージ領域に格納することであり、いわゆる自動ストレージ領域はプロセスのスタック空間であり、通常のローカル変数はデフォルトでスタック空間に格納されるので、autoで修飾する必要はありません.autoは、グローバル変数が静的領域に格納されているに違いないため、グローバル変数を修飾することはできません.次の分析を見てください.
//  
int g1;
static int g2; // static  , g2 。

int main(void)
{
    int a; //  auto , , 
    static int b; //  static , 
}

次に、各変数のメモリ領域の分散を示します.
上の図のユーザースタックとランタイムスタックに注意してください.これらはプログラムの実行時に動的に変化し、中の変数は誕生したり消滅したりします.具体的には、スタックに存在する変数はすべて局所変数(関数のパラメータを含む)であり、そのライフサイクルはその文を定義してから、その役割ドメインを離れるまでです.スタックに存在する変数は、いわゆるダイナミックメモリであり、これらのメモリのライフサイクルはプログラマによって指定され、malloc()がメモリを割り当ててからfree()がこのメモリを解放するまで終了します.スタックとスタックのそれぞれ上矢印と下矢印は、メモリ内の成長傾向を表します.
対照的に、読み書きセグメント(すなわち、静的領域)、コードセグメント、定数領域などのメモリ領域は、プログラムの実行中に「安定」であり、解放されず、これらの領域の内容は、プログラム全体が終了するまで保持される.
ここではスタックとスタックを重点的に強調します.
スタックの場合、スタック空間のサイズが限られていることを明確にするには、通常、32ビットのシステムの場合、プロセスのデフォルトスタック空間は8 Mであり、埋め込みLINUXシステムの場合、スタック空間のサイズは1 Mのように調整される可能性があります.(マルチスレッドの場合、複数のスレッドのスタックスペースは1文字で並べられますが、中間はゼロ権限メモリで警戒領域を構築して保護されます).スタックスペースにはローカル変数が格納されているため、以下の場合はローカル変数を使用するのに適していません.
第一に、巨大な変数です.たとえば2000要素の配列では、大きなデータ量がスタックをオーバーフローさせる可能性があります.
第二に、動的なデータです.例えば、動的に増加したチェーンテーブルでは、プログラムの実行初期は大きくないが、プログラムは後でチェーンテーブルのノード数を予測することができず、このような動的なデータもスタック空間で保存することはできない.
スタック空間の割り当てと解放はシステムによって自動的に行われるため、その実行効率は高速であるため、一時的に解放できるデータを格納するのに適している.
スタックスペースは、プログラムの実行時に大部分のデータの本当の練習場であり、この部分のスペースの割り当てと解放は完全にプログラマーによって制御されるため、メモリの自由領域とも呼ばれ、自由は慎重を意味し、割り当てだけが解放されなければ、メモリはすぐに使用されます.そのため、スタックスペースはより責任を負う必要がある場所です.次のコードを見てください.
char * func(void)
{
	char *p = malloc(100); //  100bytes 
	return p; //  , 
}

int main(void)
{
	char *k;
	k = func();
	if(k == NULL)
		return -1; //  !
	... //  , 
	...
	free(k); //  
}

ダイナミックメモリの使用には、次の点に注意してください.
1、使い終わったら、必ず解放してください.
2.解放しない場合、ブロックメモリはプログラムがすべて終了するまで解放されない.
3 free()は、動的メモリ(すなわちmalloc()またはcalloc()またはrealloc()によって割り当てられたメモリ)のみを解放できます.
4、動的メモリにアクセスする唯一の方法は、動的メモリが匿名であるため、ポインタを採用することです.
以上のコードの3行目は、charポインタがメモリ内の各バイトを容易に遍歴できるため、1つのcharポインタでこのダイナミックメモリをインデックスします.このメモリが特殊なデータ型を格納するために使用されている場合は、必要なタイプポインタで遍歴すればいいです.