web-dev-qa-db-ja.com

定数変数はCのどこに保存されますか?

定数変数はどこに保存されているのでしょうか。グローバル変数と同じメモリ領域にありますか?それともスタック上にありますか?

51
user188276

それらの格納方法は実装の詳細です(コンパイラーに依存します)。

たとえば、GCCコンパイラでは、ほとんどのマシンで、読み取り専用の変数、定数、およびジャンプテーブルがテキストセクションに配置されます。

39
Robert Harvey

特定のプロセッサが従うデータセグメンテーションに応じて、5つのセグメントがあります。

  1. コードセグメント-コード、ROMのみを保存
  2. BSS(またはSymbolによって開始されるブロック) Data segment-初期化されたグローバル変数および静的変数を格納します
  3. スタックセグメント-すべてのローカル変数および関数のリターンアドレスなどに関するその他の情報を格納します
  4. ヒープセグメント-すべての動的割り当てはここで行われます
  5. データ BSS(またはシンボルによって開始されるブロック) segment-初期化されていないグローバル変数および静的変数を保存します

データとBSSセグメントの違いは、前者は初期化されたグローバル変数と静的変数を格納し、後者は未初期化の変数を格納することに注意してください。

さて、なぜ定数変数がどこに保存されているのかを伝えなければならないのに、なぜデータのセグメンテーションについて話しているのですか...理由があります...

すべてのセグメントには、すべての定数が保存される書き込み保護領域があります。

例えば:

  • ローカル変数であるconst intがある場合、スタックセグメントの書き込み保護領域に格納されます。
  • Const varで初期化されたグローバルがある場合、データセグメントに格納されます。
  • 初期化されていないconst varがある場合、BSSセグメントに格納されます...

要約すると、「const」は単なるデータQUALIFIERです。つまり、最初にコンパイラが変数を格納するセグメントを決定し、次に変数がconstである場合、書き込み保護領域に格納する資格があります。その特定のセグメント。

31
wrapperm

コードを考慮してください:

_const int i = 0;
static const int k = 99;

int function(void)
{
    const int j = 37;
    totherfunc(&j);
    totherfunc(&i);
  //totherfunc(&k);
    return(j+3);
}
_

通常、iはテキストセグメントに格納できます(固定値を持つ読み取り専用変数です)。テキストセグメントにない場合は、グローバル変数の横に保存されます。ゼロに初期化されると、「bss」セクション(ゼロ化された変数が通常割り当てられる)または「data」セクション(初期化された変数が通常割り当てられる)にある可能性があります。

コンパイラがkが未使用であると確信している場合(単一のファイルに対してローカルである可能性があるため)、オブジェクトコードにまったく表示されない可能性があります。 kを参照するtotherfunc()の呼び出しがコメント化されていない場合、kにアドレスを割り当てる必要があります。おそらく、iと同じセグメントにあります。

定数(定数の場合、それでも変数ですか?)jは、おそらく従来のC実装のスタックに表示されます。 (comp.std.cニュースグループで質問している場合、標準では自動変数がスタックに表示されるとは言われていないと言う人がいます。幸いなことに、SOはcompではありません。 std.c!)

おそらく定数整数へのポインタを期待する関数に変数を参照渡ししたため、変数を強制的に表示することに注意してください。アドレスが取得されなかった場合、jおよびkをコードから完全に最適化できます。 iを削除するには、コンパイラはプログラム全体のすべてのソースコードを知っている必要があります。他の翻訳単位(ソースファイル)でアクセスできるため、簡単に削除できません。プログラムが共有ライブラリの動的ロードにふける場合、二重ではありません。それらのライブラリの1つは、そのグローバル変数に依存する可能性があります。

(スタイル的に-変数iおよびjには、より長く意味のある名前を付ける必要があります。これは単なる例です!)

12

コンパイラ、システム機能、コンパイル時の構成に依存します。

gccputs 特に指示がない限り、.textセクションの読み取り専用定数。

4

オフコースではない、なぜなら

1)bssセグメントは、明らかに別の型が存在する非inilized変数を格納します。

       (I) large static and global and non constants and non initilaized variables it stored .BSS section.

       (II) second thing small static and global variables and non constants and non initilaized variables stored in .SBSS section this included in .BSS segment.

2)データセグメントは、3つのタイプを持つ初期化された変数です。

      (I) large static and global and initlaized and non constants variables its stord in .DATA section.
      (II) small static and global and non constant and initilaized variables its stord in .SDATA1 sectiion.
     (III) small static and global and  constant and initilaized OR non initilaized variables its stord in .SDATA2 sectiion.

上記の小さな手段と大きな手段はコンパイラーに依存します。例えば、小さな手段は8バイト未満、大きな手段は8バイト以上の値です。

しかし、私の疑問は、ローカル定数がどこにあるかです?????????

2
mohan

通常、これらは読み取り専用のデータセクションに格納されます(グローバル変数のセクションには書き込み権限があります)。そのため、アドレスを取得して定数を変更しようとすると、アクセス違反、つまりセグメンテーション違反が発生する可能性があります。

しかし、それは実際にハードウェア、OS、コンパイラに依存します。

1
elder_george

これはほとんどの経験に基づいた推測ですが、定数は通常、コンパイル済みプログラムの実際のCPU命令に即時データとして格納されると思います。つまり、ほとんどの命令には、アドレスからデータを取得するためのスペースが含まれていますが、それが定数の場合、スペース自体に値を保持できます。

1
Lee B

アドオンとして、リンクプロセス中に最終実行可能ファイルのメモリレイアウトが決定されることをご存知のように、別の入力ファイルからの共通シンボルが配置されるCOMMONと呼ばれるセクションがもう1つあります。 .bssセクションの下。

0
achoora

読み取り専用変数であるため、テキストセグメントに格納する必要があります。 http://shirleyanengineer.blogspot.in/2017/05/memory-layout-of-process.html

0
Shirley V

グローバルと定数は、完全に分離された2つのキーワードです。どちらか一方、どちらでもない、または両方を持つことができます。

変数がメモリのどこに保存されるかは、構成によって異なります。 heap および stack を少し読んでください。これにより、より多くの(そして、もし可能であれば、より良く、より具体的な)質問をするための知識が得られます。

0
Mizipzor

X86_64 GNU/Linuxシステムで確認しました。 'const'変数へのポインターを使用して、値を変更できます。 objdumpを使用しました。テキストセグメントに「const」変数が見つかりませんでした。 'const'変数はスタックに保存されます。 「const」は「C」のコンパイラ指令です。コンパイラーは、 'const'変数を変更するステートメントに遭遇するとエラーをスローします。

0
Gangadhar

一部の定数は保存されていません。

次のコードを考慮してください:int x = foo(); x *= 2;。コンパイラーは乗算をx = x+x;に変換する可能性があります。これにより、メモリーから数値2をロードする必要が減ります。

0
MSalters

まったく保存されない場合があります。

次のようなコードを検討してください。

#import<math.h>//import PI
double toRadian(int degree){
  return degree*PI*2/360.0;
}

これにより、プログラマーは何が起こっているかのアイデアを収集できますが、コンパイラーは、コンパイル時に定数式を評価することにより、その一部を最適化することができます。まったく。

0
tomjen