定数変数はどこに保存されているのでしょうか。グローバル変数と同じメモリ領域にありますか?それともスタック上にありますか?
それらの格納方法は実装の詳細です(コンパイラーに依存します)。
たとえば、GCCコンパイラでは、ほとんどのマシンで、読み取り専用の変数、定数、およびジャンプテーブルがテキストセクションに配置されます。
特定のプロセッサが従うデータセグメンテーションに応じて、5つのセグメントがあります。
データとBSSセグメントの違いは、前者は初期化されたグローバル変数と静的変数を格納し、後者は未初期化の変数を格納することに注意してください。
さて、なぜ定数変数がどこに保存されているのかを伝えなければならないのに、なぜデータのセグメンテーションについて話しているのですか...理由があります...
すべてのセグメントには、すべての定数が保存される書き込み保護領域があります。
例えば:
要約すると、「const」は単なるデータQUALIFIERです。つまり、最初にコンパイラが変数を格納するセグメントを決定し、次に変数がconstである場合、書き込み保護領域に格納する資格があります。その特定のセグメント。
コードを考慮してください:
_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
には、より長く意味のある名前を付ける必要があります。これは単なる例です!)
コンパイラ、システム機能、コンパイル時の構成に依存します。
gcc
puts 特に指示がない限り、.text
セクションの読み取り専用定数。
オフコースではない、なぜなら
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バイト以上の値です。
しかし、私の疑問は、ローカル定数がどこにあるかです?????????
通常、これらは読み取り専用のデータセクションに格納されます(グローバル変数のセクションには書き込み権限があります)。そのため、アドレスを取得して定数を変更しようとすると、アクセス違反、つまりセグメンテーション違反が発生する可能性があります。
しかし、それは実際にハードウェア、OS、コンパイラに依存します。
これはほとんどの経験に基づいた推測ですが、定数は通常、コンパイル済みプログラムの実際のCPU命令に即時データとして格納されると思います。つまり、ほとんどの命令には、アドレスからデータを取得するためのスペースが含まれていますが、それが定数の場合、スペース自体に値を保持できます。
アドオンとして、リンクプロセス中に最終実行可能ファイルのメモリレイアウトが決定されることをご存知のように、別の入力ファイルからの共通シンボルが配置されるCOMMONと呼ばれるセクションがもう1つあります。 .bssセクションの下。
読み取り専用変数であるため、テキストセグメントに格納する必要があります。 http://shirleyanengineer.blogspot.in/2017/05/memory-layout-of-process.html
X86_64 GNU/Linuxシステムで確認しました。 'const'変数へのポインターを使用して、値を変更できます。 objdumpを使用しました。テキストセグメントに「const」変数が見つかりませんでした。 'const'変数はスタックに保存されます。 「const」は「C」のコンパイラ指令です。コンパイラーは、 'const'変数を変更するステートメントに遭遇するとエラーをスローします。
一部の定数は保存されていません。
次のコードを考慮してください:int x = foo(); x *= 2;
。コンパイラーは乗算をx = x+x;
に変換する可能性があります。これにより、メモリーから数値2をロードする必要が減ります。
まったく保存されない場合があります。
次のようなコードを検討してください。
#import<math.h>//import PI
double toRadian(int degree){
return degree*PI*2/360.0;
}
これにより、プログラマーは何が起こっているかのアイデアを収集できますが、コンパイラーは、コンパイル時に定数式を評価することにより、その一部を最適化することができます。まったく。