Memory 为什么打印的内存地址是40位和48位地址的混合体?

Memory 为什么打印的内存地址是40位和48位地址的混合体?,memory,rust,Memory,Rust,我试图理解Rust处理内存的方式,我有一个小程序,可以打印一些内存地址: fn main() { let a = &&&5; let x = 1; println!(" {:p}", &x); println!(" {:p} \n {:p} \n {:p} \n {:p}", &&&a, &&a, &a, a); } 这将打印以下内容(不同的运行会有所不同): 0x235d0ff61

我试图理解Rust处理内存的方式,我有一个小程序,可以打印一些内存地址:

fn main() {
    let a = &&&5;
    let x = 1;
    println!(" {:p}", &x);
    println!(" {:p} \n {:p} \n {:p} \n {:p}", &&&a, &&a, &a, a);
}
这将打印以下内容(不同的运行会有所不同):

0x235d0ff61c
0x235d0ff710
0x235d0ff728
0x235d0ff610
0x7ff793f4c310

这实际上是40位和48位地址的混合。为什么是这种混合?另外,有人能告诉我为什么地址(2、3、4)不在8字节分隔的位置(因为
std::mem::size\u of val(&a)
给出了8)?我在AMD x-64处理器(Phenom | | X4)上运行Windows 10,内存为24GB。

所有地址的大小都相同,Rust只是不打印尾随的0位数字

实际内存布局是操作系统的一个实现细节,但是
a
在不同于所有其他变量的内存区域中打印位置的原因是
a
实际上存在于加载的二进制文件中,因为它是一个编译器已经可以计算的值。所有其他变量都是在运行时计算的,并在堆栈上运行

请参见以下内容的汇编结果:

.L_uunnamed_4
包含值5
.L_uunnamed_5
.L_uunnamed_6
.L_uunnamed_1
&5
&5

因此,
.L_uunnamed_1
是您系统上位于
0x7ff793f4c310
的位置。当
0x235d0ff???
在堆栈上并在代码的红色和蓝色区域中计算时

这实际上是40位和48位地址的混合。为什么是这种混合

这不是一个真正的混合,Rust只是不显示前导零。它实际上是关于操作系统在地址空间中映射程序的各个组件(数据、bss、堆和堆栈)的位置

另外,有人能告诉我为什么地址(2、3、4)不在以8字节分隔的位置(因为std::mem::size_of_val(&a)给出了8)

因为
println
是一个宏,它在stackframe中扩展为一组内容,因此在frame final code()中,您的值不会彼此相邻地定义。尽管即使是这样,也不能保证编译器不会重用现在的死内存来节省帧大小