2

たとえば、変数を定義した後:

int a=2;

その後、「a」を 2 として使用できます。
私が最初に c/c++ を学んだとき、私はそれを当然のことと思っていました。
しかし、「ポインター」の概念と変数のアドレスを学んだ後、私は混乱しています。

の場合int* p=&i;、「i」は int です。p には i のアドレスがあることがわかっているので、*p を使用して i の値を取得できます。しかし、さらに先に進むと、「p」はどのようにアクセスされるのでしょうか? p は名前で参照する必要があるように見えましたね。

今では、アドレスを介して変数にアクセスする方が自然で理解しやすいように思えます。
しかし今、変数にアクセスする最も簡単な方法を使用するときのメカニズムについて混乱しています。
の場合と同様に、int a=2;「a」という名前はどこに格納されていますか?

「a」を使用すると、「a」または「2」が格納されているメモリにアクセスする動作と同等になるのはなぜですか?

4

3 に答える 3

9

ここでaは単なる象徴的な名前です。ローカル変数の場合、どこにも保存されません。コンパイラは、コンパイル段階で実際の値 (スタック上またはレジスタ内にある可能性があります) を参照して単純に使用し、その後破棄します。

aコンパイラによって生成されたアセンブリを見ると、そこに (またはコメントに)表示されていないことに気付くでしょう。コンパイラは変数をどこかに適合させ、後でその場所を使用します ( eaxx86 のレジスタのように)。

@1LLVM アセンブリ (これは非常に興味深いものです) を見ると、コンパイラが変数を単に, @2, @3...として扱っていることに気付くでしょう。

一方、aがグローバル変数 (およびstatic1 以外) の場合、その名前は実際には変数を参照するためにシンボル テーブルで使用されます。しかし、それは逆です。変数は名前なしでどこかに配置され、シンボル テーブルはその名前をその場所にマップして、他のプログラムがそれを見つけられるようにします。


補足として、プログラムがデバッグ データを使用してコンパイルされている場合、名前aはそこに保存されるため、デバッガーはそれを表示して、何が起こっているのかを理解するのに役立ちます。

于 2012-07-31T07:55:39.237 に答える
3

これを抽象化と呼びます。保存方法とa保存場所は意図的に指定されていません。コンパイラがそれを処理します。

実際にaは、 が関数内のローカル変数である場合、呼び出し時にその関数のスタック フレームに格納されます。スタック フレームのレイアウトはコンパイル時に決定され、その後は変更されません。実際には、コンパイラはa(スタック フレームの開始に関連する) 相対アドレスを生成します。これは、関数が実際に実行される時点で絶対アドレスに変換され、スタック フレームの開始アドレスに変換されます。知られている。

于 2012-07-31T07:54:34.593 に答える
2

「a」や「p」などのすべての記号は、コンパイルおよびリンク処理後にアドレスに変換されます。シンボルは、関数がそれらを名前で使用するためのものです。メモリアドレスのタグのようなものです。「p」は「a」のアドレスを保持していますが、ポインタ「p」もコンパイラによってアドレスに変更されます。

于 2012-07-31T07:54:52.340 に答える