为什么 32 位和 64 位地址有两种不同的长度?

Sur*_*ala 2 c memory

当我在 64 位机器上运行此代码时:

?#?include ?<stdio.h>
int main() 
{ 
    int a[10]; 
    printf("%p",&a);
    return 0;  
}
Run Code Online (Sandbox Code Playgroud)

它输出:

0x7fffe9ebf984 (14 digits)
Run Code Online (Sandbox Code Playgroud)

在一本教科书中,我发现了这个:

我的电脑的内存地址是 32 位的,用八位十六进制数字表示。

我的问题是:

为什么 32 位和 64 位地址有两种不同的长度?

32 位地址如何用 8 位数字表示,64 位数字如何用 14 位数字表示?

Mar*_*all 7

首先,0x前缀表示后面是一个十六进制(以 16 为基数)数字。十六进制系统扩展了十进制系统中的数字集(0 到 9),其中 a、b、c、d、e 和 f 分别代表十进制数字 10、11、12、13、14 和 15。我们更喜欢十六进制数而不是十进制数(至少在字长是四的倍数的机器上)的原因是每个十六进制数字方便地对应于一组 4 位(二进制数字)。例如:

Hexadecimal: 3
Binary:      0 0 1 1
--------------------
Hexadecimal: F
Binary:      1 1 1 1
Run Code Online (Sandbox Code Playgroud)

通常当我们谈到机器是“32位”或“64位”时,我们谈论的是虚拟地址长度——即从用户模式进程的角度来看构成内存地址的位数。(这通常但不一定与字长一致。)

在 x86-32 机器上,例如旧的 Pentium,虚拟地址大小为 32 位。这意味着可以使用八个十六进制数字写入地址。例如,0x80000000代表 2 GiB 标记。虚拟地址为 32 位这一事实意味着任何给定进程只能直接引用 4 GiB 内存(实际上,可用内存量甚至更小!)。

对于当今的许多应用程序(例如大型内存数据库)来说,4 GiB 的虚拟内存太小,无法容纳数据集。这促使了 64 位机器的引入,例如基于 x86-64 架构的机器。理论上,64 位机器应该能够寻址 16 EiB。但是,正如其他人所指出的,x86-64 架构目前通过要求虚拟地址采用规范形式来将虚拟地址大小限制为 48 位。

顺便提及,规范地址空间的较低部分中的地址可以使用12个十六进制数字来写入。像往常一样,我们在打印时省略前导零。

我们不太可能很快看到从 32 位计算完全转变为 64 位计算(如果有的话)。仍然有许多应用,特别是在嵌入式系统中,根本不需要 64 位地址支持的内存量;事实上,16 位甚至 8 位微控制器仍然很常见。


Fer*_*cia 5

该内存地址有 12 位数字,而不是 14 位数字。每个数字都是一个 4 位字。12*4 = 48,也就是256TB的地址空间。当前的 CPU 仅使用完整 64 位地址空间的低 48 位,因为这允许构建更便宜的晶体管(我们不会在不久的将来完全使用我们可以从 64 位使用的内存)。当我们达到 48 位限制时,制造商可能会创建真正使用 64 位完整地址空间的 CPU,但现在这不是必需的。