web-dev-qa-db-ja.com

私の変数はCのどこに格納されていますか

メモリはデータ、ヒープ、スタック、コードの4つのセグメントに分けられます。グローバル変数、スタティック変数、定数データ型、ローカル変数(関数内で定義および宣言)、変数(メイン関数内)、ポインタそして、動的に割り当てられた空間(mallocとcallocを使って)はメモリに格納されますか?

それらは次のように割り当てられると思います。

  • グローバル変数-------> data
  • 静的変数-------> data
  • 定数データ型-----> code
  • ローカル変数(関数内で宣言および定義)--------> stack
  • Main関数で宣言および定義された変数-----> heap
  • ポインター(例えば、char *arrint *arr)-------> heap
  • 動的割り振りスペース(mallocおよびcallocを使用)--------> stack

これらの変数については、Cの観点からのみ言及しています。

私はCに慣れていないので私が間違っているなら私を訂正してください.

124
starkk92

あなたはこれらの権利のいくつかを手に入れました、しかし質問を書いた人は誰でも少なくとも1つの質問にあなたをだましました:

  • グローバル変数-------> data(正しい)
  • 静的変数-------> data(正しい)
  • 定数データ型----->コードおよび/またはデータ。定数自体がデータセグメントに格納され、それへの参照がコードに埋め込まれる状況については、文字列リテラルを検討してください。
  • ローカル変数(関数内で宣言および定義されている)--------> stack(正しい)
  • main関数で宣言および定義された変数-----> ヒープ またスタックする(先生があなたをだまそうとしていた)
  • ポインタ(例:char *arrint *arr)-------> ヒープ 状況に応じてデータまたはスタック。 Cを使用すると、グローバルポインタまたはstaticポインタを宣言できます。この場合、ポインタ自体がデータセグメントに入ります。
  • 動的に割り当てられたスペース(malloccallocreallocを使用)--------> スタック ヒープ

「スタック」が正式に「自動ストレージクラス」と呼ばれることは言及する価値があります。

177
dasblinkenlight

それらのメモリセグメントについて知ることに興味があるかもしれないそれらの将来の訪問者のために、私はCの5つのメモリセグメントについて重要なポイントを書いています:

いくらか上がる:

  1. Cプログラムが実行されるときはいつでも、プログラム実行のためにいくらかのメモリがRAMに割り当てられます。このメモリは、頻繁に実行されるコード(バイナリデータ)、プログラム変数などを格納するために使用されます。以下のメモリセグメントはほぼ同じです。
  2. 通常、3種類の変数があります:
    • ローカル変数(Cでは自動変数とも呼ばれます)
    • グローバル変数
    • 静的変数
    • グローバル静的変数またはローカル静的変数を持つことができますが、上記の3つは親の型です。

Cの5つのメモリセグメント:

1.コードセグメント

  • テキストセグメントとも呼ばれるコードセグメントは、頻繁に実行されるコードを含むメモリの領域です。
  • コードセグメントは、バッファオーバーフローなどのプログラミングバグによって上書きされるリスクを回避するために、多くの場合読み取り専用です。
  • コードセグメントには、ローカル変数(はC では自動変数とも呼ばれます)、グローバル変数などのようなプログラム変数は含まれていません。
  • Cの実装に基づいて、コードセグメントには読み取り専用の文字列リテラルを含めることもできます。たとえば、printf("Hello, world")を実行すると、文字列 "Hello、world"がcode/textセグメントに作成されます。これはLinux OSのsizeコマンドで確認できます。
  • 続きを読む

データセグメント

データセグメントは下の2つの部分に分割され、通常はヒープ領域の下、または一部の実装ではスタックの上にありますが、データセグメントはヒープ領域とスタック領域の間にはありません。

2.未初期化データセグメント

  • このセグメントはbssとしても知られています。
  • これは、次のものを含むメモリの一部です。
    1. 未初期化グローバル変数(ポインタ変数を含む)
    2. 未初期化定数グローバル変数
    3. 初期化されていないローカル静的変数
  • 初期化されていないグローバルまたは静的ローカル変数は、未初期化データセグメントに格納されます。
  • たとえば、グローバル変数int globalVar;または静的ローカル変数static int localStatic;は、未初期化データセグメントに格納されます。
  • グローバル変数を宣言し、それを0またはNULLとして初期化すると、それでも初期化されていないデータセグメントまたはbssになります。
  • 続きを読む

3.初期化データセグメント

  • このセグメントには以下が格納されています。
    1. 初期化されたグローバル変数(ポインタ変数を含む)
    2. 初期化定数グローバル変数
    3. 初期化されたローカル静的変数
  • たとえば、グローバル変数int globalVar = 1;または静的ローカル変数static int localStatic = 1;は、初期化されたデータセグメントに格納されます。
  • このセグメントは、初期化された読み取り専用領域と初期化された読み書き領域にさらに分類されますになります。 初期化された定数グローバル変数は初期化された読み取り専用領域に入りますが、実行時に値を変更できる変数は初期化された読み書き領域に入ります。
  • このセグメントのサイズは、プログラムのソースコード内の値のサイズによって決まり、実行時には変わりません
  • 続きを読む

スタックセグメント

  • スタックセグメントは、関数内で作成される変数を格納するために使用されます(関数はメイン関数またはユーザー定義関数)、のような変数
    1. ローカル変数関数の--- (ポインタ変数を含む)
    2. 関数に渡される引数
    3. 返信先
  • 関数の実行が終了するとすぐに、スタックに格納されている変数は削除されます。
  • 続きを読む

5.ヒープセグメント

  • このセグメントは動的メモリ割り当てをサポートするためのものです。プログラマがメモリを動的に割り当てたい場合は、Cではmalloccalloc、またはreallocメソッドを使用して行われます。
  • たとえば、int* prt = malloc(sizeof(int) * 2)の場合、8バイトがヒープに割り当てられ、その場所のメモリアドレスが返されてptr変数に格納されます。 ptr変数は、宣言または使用方法に応じて、スタックまたはデータセグメントのどちらかにあります。
  • 続きを読む
100
hagrawal

あなたの間違った文章を修正

constant data types ----->  code //wrong

ローカル定数変数-----> stack

初期化されたグローバル定数変数----->データセグメント

未初期化グローバル定数変数-----> bss

variables declared and defined in main function  ----->  heap //wrong

main関数で宣言および定義された変数-----> stack

pointers(ex:char *arr,int *arr) ------->  heap //wrong

dynamically allocated space(using malloc,calloc) --------> stack //wrong

ポインタ(例:char * arr、int * arr)------->ポインタ変数のサイズはスタックになります。

Nバイトのメモリーを(mallocまたはcallocを使用して)動的に割り当ててから、それを指すようにポインター変数を作成するとします。 nバイトのメモリがヒープにあり、ポインタ変数はnバイトのメモリチャンクの開始ポインタを格納するためのスタックになる4バイト(64ビットマシンの場合8バイト)を必要とします。

注:ポインタ変数は任意のセグメントのメモリを指すことができます。

int x = 10;
void func()
{
int a = 0;
int *p = &a: //Now its pointing the memory of stack
int *p2 = &x; //Now its pointing the memory of data segment
chat *name = "ashok" //Now its pointing the constant string literal 
                     //which is actually present in text segment.
char *name2 = malloc(10); //Now its pointing memory in heap
...
}

動的割り当て領域(malloc、callocを使用)-------->ヒープ

8
rashok

一般的なデスクトップアーキテクチャは、プロセスの仮想メモリをいくつかに分割しますセグメント

  • テキストセグメント:実行可能コードを含みます。命令ポインタはこの範囲の値を取ります。

  • データセグメント:大域変数(すなわち静的リンケージを有するオブジェクト)を含む。読み取り専用データ(文字列定数など)と未初期化データ( "BSS")に分割されています。

  • スタックセグメント:プログラム用の動的メモリ、すなわちフリーストア(「ヒープ」)およびすべてのスレッド用のローカルスタックフレームを含む。伝統的に、CスタックとCヒープは反対側からスタックセグメントに成長していましたが、安全性が高すぎるため慣習は中止されたと思います。

Cプログラムは通常、静的記憶期間を持つオブジェクトをデータセグメントに、動的に割り当てられたオブジェクトをフリーストアに、自動オブジェクトをそれが存在するスレッドの呼び出しスタックに入れます。

古いx86リアルモードや組み込みデバイスなどの他のプラットフォームでは、明らかに事情が大きく異なります。

6
Kerrek SB

これらの変数はCの観点からのみ参照しています。

C言語の観点からすると、重要なのは範囲、範囲、リンケージ、およびアクセスだけです。アイテムが異なるメモリセグメントにどのようにマッピングされるかは個々の実装次第であり、それは異なります。言語標準はメモリセグメントについては話しませんまったく。ほとんどの現代建築はほとんど同じように機能します。ブロックスコープ変数と関数引数はスタックから割り当てられ、ファイルスコープと静的変数はデータまたはコードセグメントから割り当てられ、動的メモリはヒープから割り当てられ、一部の定数データは読み取り専用セグメントに格納されます。など.

5
John Bode
  • 変数/自動変数--->スタックセクション
  • 動的に割り当てられた変数--->ヒープセクション
  • 初期化されたグローバル変数 - >データセクション
  • 未初期化グローバル変数 - >データセクション(bss)
  • 静的変数 - >データセクション
  • 文字列定数 - >テキスト部/コード部
  • 機能 - >テキストセクション/コードセクション
  • テキストコード - >テキストセクション/コードセクション
  • レジスタ - > CPUレジスタ
  • コマンドライン入力 - >環境/コマンドラインセクション
  • 環境変数 - >環境/コマンドラインセクション
1
prashad

ポインタ(例:char * arr、int * arr)------->ヒープ

いいえ、それらはスタック上にあってもデータ・セグメント内にあってもかまいません。彼らはどこでも指すことができます。

1
Steve Wellens

ストレージについて留意する必要があることの1つは、 as ifルール です。コンパイラは変数を特定の場所に置く必要はありません-代わりに、コンパイルされたプログラムが動作する限り、好きな場所に変数を置くことができますas ifそのルールに。これはすべてのストレージに適用されますdurations。例えば:

  • すべてにアクセスされるわけではない変数は完全に排除することができます-どこにもストレージがありません。 -生成されたアセンブリコードに42があるが、404の兆候がないことを確認します。
  • アドレスが取得されない自動保存期間を持つ変数は、メモリに保存する必要はまったくありません。 例はループ変数です
  • constまたは実質的にconstである変数は、メモリ内にある必要はありません。 -コンパイラーは、fooが実質的にconstであることを証明し、その使用をコードにインライン化できます。 barには外部リンケージがあり、コンパイラは現在のモジュールの外部で変更されないことを証明できないため、インライン化されません。
  • mallocで割り当てられたオブジェクトは、ヒープから割り当てられたメモリに存在する必要はありません! -コードにmallocの呼び出しがなく、値42もメモリに保存されず、レジスタに保持されていることに注意してください!
  • したがって、mallocによって割り当てられたオブジェクトと参照は、freeでオブジェクトの割り当てを解除せずに失われますneed notメモリのリーク...
  • mallocによって割り当てられたオブジェクトは、ヒープ内にある必要はありません Unixenのプログラムブレーク(sbrk(0))...
0
Antti Haapala