1

メモリ内の C++ リテラル定数ストレージはどこにありますか? スタックまたはヒープ?

int *p = &2

間違っている。理由を知りたいですか?ありがとう

--------------------------------------------------

私の質問は、「メモリ内の C++ リテラル定数ストレージの場所」です。int *p = &2

間違っている」、私の質問ではありません。

4

3 に答える 3

6

詳細はマシンによって異なりますが、最も一般的な種類のマシンとオペレーティング システムを想定しています...すべての実行可能ファイルには、CODE、BSS、DATA などのいくつかの「セグメント」が含まれています。

CODE は、すべての実行可能なオペコードを保持します。実際、TEXT という名前が付けられることが多いのは、何十年も前に人々が意味を成していたからです。通常は読み取り専用です。

BSS は初期化されていないデータです。実際には実行可能ファイルに存在する必要はありませんが、プログラムの実行開始時にオペレーティング システムのローダーによって割り当てられます。

DATA は、int8、int16、int32 などのリテラル定数と、float、文字列リテラル、およびコンパイラとリンカが生成する奇妙なものを保持します。これはあなたが尋ねているものです。ただし、次のように、変数として使用するために定義された定数のみを保持します。

const long x = 2;

ただし、ソース コードで使用されているが、変数と密接に関連付けられていないリテラル定数を保持する可能性は低いです。唯一の '2' は、コンパイラによって直接処理されます。たとえば、Cでは、

print("%d", 2);

コンパイラに print() へのサブルーチン呼び出しを作成させ、文字列リテラル "%d" と値 2 へのポインタを 64 ビット マシン上の 64 ビット整数としてプッシュするオペコードを記述します (あなたはそうではありません)。まだ 32 ビット ハードウェアを使用しているラガードの 1 人ですね? :) の後に、('print' サブルーチンの識別子) のサブルーチンにジャンプするオペコードが続きます。

「%d」リテラルは DATA に入ります。2 はそうではありません。スタックに整数を詰め込むオペコードに組み込まれています。これは、実際には「ロード レジスタ RAX 即時」の後に値 2 が続き、その後に「プッシュ レジスタ RAX」が続く場合もあれば、単一のオペコードでジョブを実行できる場合もあります。したがって、最終的な実行可能ファイルでは、2 は CODE (別名 TEXT) セグメントにあります。

通常、その値またはオペコードへのポインターを作成することはできません。C のような高水準言語が何をするかという点では意味がありません (そして、オペコードとセグメントについて話している場合、C は「高水準」です)。「&2」はエラーになるだけです。

さて、オペコードへのポインターを持つことは完全に不可能ではありません。C で関数を定義するか、C++ でオブジェクト メソッド、コンストラクター、またはデストラクターを定義するときはいつでも、関数の名前は、その関数からコンパイルされたマシン コードの最初のオペコードへのポインターと考えることができます。たとえば、括弧のない print() は関数へのポインターです。サンプルコードが関数内にあり、正しいオフセットを推測した場合、ポインター演算を使用して、オペコードに囲まれた「即時」値 2 を指すことができますが、これは現代の CPU にとって簡単ではなく、確かに初心者向けではありません。

于 2012-08-15T07:42:46.713 に答える
0

C++03 標準の関連条項を引用させてください。5.3.1/2

単項 & 演算子の結果は、そのオペランドへのポインターです。オペランドは左辺値でなければなりません。

整数リテラルは右辺値です (ただし、C++03 標準では直接の引用は見つかりませんでしたが、C++11 では 3.10/1 で補足として言及されています)。したがって、整数リテラルのアドレスを取得することはできません。

2正確な保管場所については、使用状況によって異なります。機械語命令の一部である場合もあれば、最適化されて取り除かれている場合もありj=i*2ますj=i+i。それに頼ってはいけません。

于 2012-08-15T08:41:51.953 に答える
0

2 つの質問があります。

リテラル定数はどこに保存されますか? 文字列リテラル (実際のオブジェクト) を除いて、実装が必要とするほとんどの場所。それは通常、それらをどうするかによって異なりますが、多くのアーキテクチャでは、整数定数 (および多くの場合、 のような特殊な浮動小数点定数0.0) は機械命令の一部になります。これが不可能な場合は、通常、コードと同じ論理セグメントに配置されます。

右辺値のアドレスを取得することが違法である理由については、主な理由は、標準でそう規定されているためです。歴史的に、このような定数はメモリ内に個別のオブジェクトとして存在しないことが多く、したがってアドレスがないため、禁止されています。今日... 他の解決策を想像することができます。コンパイラは、アドレスを取得した場合はそれらをメモリに配置するのに十分スマートであり、そうでない場合はメモリに配置できません。クラス型の右辺値にはメモリアドレスがありますルールはいくぶん恣意的です (そして、それらが何であったかに関係なく) — 願わくば、リテラルのアドレスを取ることを許可するルールは、その型int const*を ではなく にしint*ます。

于 2012-08-15T09:23:11.860 に答える