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只是一个象征性的名字。如果它是一个局部变量,它就不会存储在任何地方。编译器只是在编译阶段使用它,引用实际值(可以在堆栈上或寄存器中),然后丢弃。

If you looked at the assembly generated by compiler, you'd notice that a isn't appearing there (or maybe in comments). Compiler will fit your variable somewhere, and just use that location afterwards (like the eax register on x86).

If you looked at an LLVM assembly (which is quite interesting), you'd notice that the compiler just treats your variables as @1, @2, @3...

On the other hand, if a would be a global variable (and a non-static one), the name would actually be used in the symbol table to reference the variable. But it'd be the other way around — variable would be placed somewhere without the name, and the symbol table would map that name to the location so that other programs could find it.


As a side note: if the program is compiled with debug data, the name a is stored there so that the debugger could display it to help you understanding what's happening.

于 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 回答