2012-07-31 48 views
2

例如,后我们定义一个变量:当按名称引用时,名称的存储位置在哪里?

int a=2; 

我们可以用 “a” 作为2之后。
当我第一次学习c/C++的时候,我认为这是理所当然的。
但是,当我了解到“指针”的概念和变量的地址后,我很困惑。

如果int* p=&i;,其中“i”是一个int。我知道p有我的地址,所以我们可以用* p来得到i的值。但是如果我们走得更远,如何访问“p”?似乎p必须按名称引用,对吧?

现在,通过它的地址访问一个变量对我来说更加自然,也更容易理解。
但现在,我对使用最简单的方法访问变量时的机制感到困惑。
int a=2;的情况一样,名称“a”的存储位置在哪里?

为什么如果我们使用“a”,它相当于访问存储“a”或“2”的内存的行为?

+4

全部编译完成后,这些符号名称就没有任何内容了。它们都被缩减为内存地址和/或寄存器。变量名称仅供读者使用。 – Mysticial 2012-07-31 07:54:35

回答

9

这里a只是一个象征性的名字。如果它是一个局部变量,它不会存储在任何地方。编译器在编译阶段简单地使用它,参考实际值(可以在堆栈中或在寄存器中),然后丢弃。

如果您查看编译器生成的程序集,您会注意到a没有出现在那里(或者在注释中)。编译器会适合你的变量,然后就使用这个位置(比如x86上的eax寄存器)。

如果你看着一个LLVM组件(这是很有趣的),你会发现,编译器只是把你的变量@1@2@3 ...

在另一方面,如果a会是一个全局变量(并且不是一个),该名称实际上将用于符号表中以引用该变量。但反过来说 - 变量会放在没有名字的地方,符号表会将该名称映射到该位置,以便其他程序可以找到它。


补充说明:如果程序与调试数据编制,名称a存储在那里,以便调试器可以显示它可以帮助您了解发生了什么。

3

这被称为抽象。故意未指定如何以及在何处存储a。编译器会为你处理它。

实际上,如果a是一个函数内部的局部变量,它将在调用时存储在该函数的栈帧中。堆栈帧的布局在编译时确定,并且在此之后不会改变。实际上,编译器将生成一个相对地址为a(相对于堆栈帧的开始),在该函数实际执行时将转换为绝对地址,并且堆栈的起始地址 - 帧是已知的。

2

在编译和链接过程之后,“a”和“p”等所有符号都将被转换为地址。这些符号仅用于按名称使用它们的功能。这就像内存地址的标签。即使“p”保存了“a”的地址,指针“p”也被编译器改变为地址。