(&)的地址给出了编译器生成的地址或加载器生成的地址?

int a; printf("address is %u", &a); 

这是哪个地址..? 我的意思是这是一个编译器生成的地址,即虚拟地址或加载器给出RAM中的物理地址..?

因为它每次打印不同的地址,我想它必须是RAM中的地址。 只是想确定一下。

请提供任何参考您的答案的链接。

正确的答案是:“这取决于。”

(printf应使用“%p”指令,并将地址转换为“void *”,以便明确定义:

 printf("%p\n", (void *)&a); 

虽然使用%u无疑适用于您使用的任何标志的特定编译器。)

正如@Alex指出的那样,如果正在进行翻译,地址是虚拟的(与大多数现代操作系统一样,或者甚至在虚拟机下运行“模拟物理”时)。 如果“a”具有静态存储持续时间,则通常在链接或加载时确定地址本身,但是在运行时(如同@Als所说,在堆栈上)如果不是。 声明为“静态”或“外部”的变量具有静态持续时间; 在函数体外声明的变量有静态持续时间; 和函数体内声明的变量,但不使用“extern”或“static”,具有自动存储持续时间(因此通常在“堆栈”上 – 尽管可以有多个堆栈,如使用POSIX线程时)。

为用户空间中的本地变量返回的地址始终是虚拟地址而不是物理地址。

在您的情况下,变量a在本地存储(堆栈)上分配,并且每次执行程序时,为您的函数分配一个堆栈空间,该变量位于此堆栈帧中的特定偏移量,因为堆栈的地址已分配每次为变量返回的地址也会不同,你的程序可能会有所不同。

在任何现代操作系统上,您在C级别上看到的所有地址都是虚拟地址。 您给出的示例是堆栈上的变量,并且每次执行时它的不同之处在于(出于安全原因)(虚拟)堆栈地址是随机的。

但无论如何,即使由加载器解析的全局符号也在进程的地址空间中具有虚拟地址。

(对于嵌入式设备,所有这些可能都不是这样,但这通常是学习C时不会遇到的)

我的意思是这是一个编译器生成的地址,即虚拟地址或RAM中给定物理地址的加载器。

假二分法。 编译器生成的地址由链接器重定位,并且由&返回的是此地址。 它是一个虚拟地址,除非您运行的是像NetWare 3这样不使用VM的奇怪地方。