CPU和内存通信

Jey*_*mon 3 c memory cpu pointers

我是程序员初学者,但我想更深入地了解这些事情.我做了一些研究并阅读了很多文字,但我还没有理解一些东西......

编码基本内容时(在C中):

int myNumber;
myNumber = 3;
printf("Here's my number: %d", myNumber);
Run Code Online (Sandbox Code Playgroud)

我发现(主要在32位CPU上)整数取代32位= 4个字节.所以在我的代码的第一行CPU进入内存.存储器是字节可寻址的,因此CPU为我的变量选择4个连续字节,并将地址存储到第一个(或最后一个)字节.

在我的代码的第二行,CPU使用他存储的MyNumber变量地址,转到内存中的那个地址,找到32位的保留空间.他现在的任务是在那里存储数字"3",所以他用序列00000000-00000000-00000000-00000011填充这四个字节.在第三行它执行相同的操作 - CPU转到内存中的该地址并加载存储在该地址中的数字.

(第一个问题 - 我明白了吗?)

我不明白的是:
32位CPU中该地址(指向该变量的指针)的大小为4字节.(这就是为什么32位CPU可以使用最大4GB的内存 - 因为只有2 ^ 32个不同的二进制长度32的地址)
现在,CPU存储这些地址的地方?他有自己的内存或缓存存储吗?而为什么它存储了32位长的地址为32位长整型?简单地在其缓存中存储实际数字而不是指向大小相同时的指针是不是更好?

最后一个 - 如果它存储在自己的缓存中的某个地方,那些整数和长度的地址是相同的(4个字节),它将需要与实际变量存储地址完全相同的空间.但变量最多可占用4GB的空间,因此CPU必须有4GB的空间来存储这些变量的地址.这听起来很奇怪..

谢谢你的帮助!
我试图理解这一点,但它太难了......: - [

Oli*_*rth 5

(第一个问题 - 我明白了吗?)

首先要认识到的是,该值可能根本不存储在主存储器中.编译器可能决定将其存储在寄存器中,因为这是更优化的.1

存储器是字节可寻址的,因此CPU为我的变量选择4个连续字节,并将地址存储到第一个(或最后一个)字节.

假设编译器决定将其存储在主存储器中,那么是的,在32位机器上,int通常是4个字节,因此将分配4个字节用于存储.

在32位CPU中,该地址的大小(指向该变量的指针)为4字节.(这就是为什么32位CPU可以使用最大4GB的内存 - 因为只有2 ^ 32个不同的二进制长度32的地址)

请注意,int指针的宽度和指针的宽度不必相同,因此不一定与地址空间的大小有关.

现在,CPU存储这些地址的位置?

在局部变量的情况下,地址有效地硬编码到可执行文件本身中,通常作为堆栈指针的偏移量.

在动态分配对象(即已经被编过的东西malloc)的情况下,程序员通常会维护一个相应的指针变量(否则会出现内存泄漏!).该指针也可以动态分配(在复杂数据结构的情况下),但是如果你回到足够远的地方,你最终会得到一个局部变量.在这种情况下,上述规则适用.

但变量最多可占用4GB的空间,因此CPU必须有4GB的空间来存储这些变量的地址.

如果你的程序独立地包含malloc数百万个ints,那么是的,你最终会得到指针所需的存储空间.但大多数程序看起来并不像那样.您通常会分配更大的对象(如数组或大结构).

高速缓存

的细节,其中东西存储是架构相关.在现代的x86上,CPU和主内存之间通常有2到3层缓存.但缓存不能独立寻址; CPU无法决定存储int缓存而不是主存储器.相反,高速缓存实际上是主存储器子集的冗余副本.

另一件需要考虑的事情是编译器通常在为对象分配存储时处理虚拟地址.在现代x86上,这些映射到专用硬件的物理地址(即与主存储器中的物理存储字节相对应的地址)以及OS支持.


或者,编译器可能能够完全优化它.