请看这个简单的程序:
int main(void)
{
char p;
char *q;
q = &p;
return 0;
}
如何确定&p
?编译器是提前计算所有此类引用,还是在运行时完成?如果在运行时完成,是否有变量表或类似的东西来查找这些内容?操作系统是否跟踪它们并仅需询问操作系统即可?
在正确的解释上下文中,我的问题可能甚至没有意义,因此请随意纠正我。
请看这个简单的程序:
int main(void)
{
char p;
char *q;
q = &p;
return 0;
}
如何确定&p
?编译器是提前计算所有此类引用,还是在运行时完成?如果在运行时完成,是否有变量表或类似的东西来查找这些内容?操作系统是否跟踪它们并仅需询问操作系统即可?
在正确的解释上下文中,我的问题可能甚至没有意义,因此请随意纠正我。
如果你不理解地址作为值和地址作为存储位置之间的区别,请搞清楚。在不理解这个关键区别的情况下,你将无法成功使用C语言。
这是一种可能的工作方式,但正如我所说的,不同的编译器可以根据自己的判断选择不同的工作方式。
p
占用一个字节,而q
占用四个字节”。 - Chris Middletonp
是char
的事实。 - Eric Lippertp
的完整地址,因为一个函数可以被不同的调用者多次调用,而 p
可以具有不同的值。p
的地址,不仅是为了取地址运算符,而且还为了生成与 p
变量一起工作的代码。在常规体系结构上,像 p
这样的局部变量是在堆栈上分配的,即相对于当前堆栈帧地址的固定偏移量位置上。q = &p
这一行只是将当前堆栈帧中 p
的地址存储到另一个在堆栈上分配的本地变量 q
中。main
。上述内容是在假设主流体系结构和编译器、以及可能被多个调用者调用的非静态函数(除 main
外)的情况下编写的。lea
(加载有效地址),偏移量由类型确定? - Chris Middletonp
可能会得到偏移量 0,变量 q
得到偏移量 4。存储在寄存器中的变量根本不会有偏移量等。如果您了解汇编语言,请查看汇编输出 - 在 GCC 下,您可以使用 gcc -S foo.c
来获取它。 - user4815162342p
是一个具有自动存储的变量。它只在所在的函数存在的同时存在。每次调用该函数时,内存都会从堆栈中获取,因此其地址可能会发生变化,在运行时无法确定。
本地变量的地址在编译时无法完全计算。局部变量通常分配在堆栈中。每个函数调用时,都会分配一个堆栈帧——一个连续的内存块,用于存储所有局部变量。堆栈帧的物理位置在编译时无法预测,在运行时才会被确定。每个堆栈帧的开头通常在专用处理器寄存器(如Intel平台上的ebp
)中存储。
同时,编译器在编译时预先确定了堆栈帧的内部内存布局,即编译器决定了局部变量在堆栈帧内的布局方式。这意味着编译器知道每个局部变量在堆栈帧内的局部偏移量。
将所有这些放在一起,我们得到一个局部变量的确切绝对地址是堆栈帧本身的地址(运行时组件)和该变量在该帧内的偏移量(编译时组件)的总和。
这基本上就是所编译代码的内容。
q = &p;
好的。它将获取当前栈帧寄存器的值,加上一些编译时常量(p
的偏移量),并将结果存储在q
中。
objdump
获取汇编代码的链接:https://dev59.com/sHM_5IYBdhLWcg3wp00X - Chris Middleton