int a;
printf("address is %u", &a);
这是哪个地址..?我的意思是这是一个编译器生成的地址,即虚拟地址或RAM中给定物理地址的加载器。?
由于每次打印不同的地址,我猜它必须是RAM中的地址。只是想确定一下。
请提供任何可以参考您答案的链接。
答案 0 :(得分:4)
在用户空间中为本地变量返回的地址始终是虚拟地址而不是物理地址。
在您的情况下,变量a
在本地存储(堆栈)上分配,并且每次执行程序时,分配给您的函数的堆栈空间,该变量位于此堆栈帧中的特定偏移量,因为每次为变量返回的地址也不同时,分配给程序的堆栈地址可能不同。
答案 1 :(得分:3)
在任何现代操作系统上,您在C级别上看到的所有地址都是虚拟地址。您给出的示例是堆栈上的变量,并且在每次执行时它的不同之处在于,出于安全原因,(虚拟)堆栈地址是随机的。
但无论如何,即使加载器解析的全局符号也在进程的地址空间中有虚拟地址。
(对于嵌入式设备,所有这些可能都不是这样,但这通常是学习C时不会遇到的事情)
答案 2 :(得分:2)
正确的答案是:“这取决于。”
(printf应使用“%p”指令,并将地址转换为“void *”,以便明确定义:
printf("%p\n", (void *)&a);
虽然使用%u无疑适用于您使用的任何标志的特定编译器。)
正如@Alex所说,如果正在进行翻译,地址是虚拟的(与大多数现代操作系统一样,或者甚至在虚拟机下运行“模拟物理”时)。如果“a”具有静态存储持续时间,则通常在链接或加载时确定地址本身,但是在运行时(如同@Als所说,在堆栈上)如果不是。声明为“静态”或“外部”的变量具有静态持续时间;在函数体外声明的变量有静态持续时间;和函数体内声明的变量,但不使用“extern”或“static”,具有自动存储持续时间(因此通常在“堆栈”上 - 尽管可以有多个堆栈,如使用POSIX线程时)。
答案 3 :(得分:0)
错误的二分法。编译器生成的地址由链接器重定位,并且该地址由&返回。它是一个虚拟地址,除非您运行的是像NetWare 3这样不使用VM的奇怪地方。我的意思是这是一个编译器生成的地址,即虚拟地址或 加载器在RAM中给出物理地址。