内存中指针的可视化

问题描述 投票:0回答:1

作为 C 初学者,我知道指针是一种特殊的数据类型,用于存储数据类型的地址。如果我计算我的 PC(64 位操作系统)中任何指针的大小,它是 8 个字节。

在内存表示中,每个地址代表 1 个字节(字节寻址...我在维基百科上读到它),所以这意味着指针将占用 8 个连续的内存块,就像整数一样(4 个字节)? 如果我们打印指针存储的地址;它会是那8个字节的基地址吗?

c pointers memory-address
1个回答
0
投票

为了可视化程序中的数据,您可能需要查看 DDD(数据显示调试器),以防您有幸使用 Linux,而不是 Windows。

但是,由于您要问的是指针如何工作以及它们在内存中的结构如何……好吧……简短的答案是“这取决于”,因为它取决于您所在的特定机器体系结构、编译器等。如果您在 x86-64 上,那么是的,指针只是 8 个后续字节(64 位),小端排序(即,从较低内存地址的最低有效字节到较高内存地址的最高有效字节),应该被解释为无符号整数,其中每个后续位都是后续 2 次方的二进制数字。

当这些位被解释为无符号整数时,应该指示特定类型(与指针关联的类型)的其他内容的内存地址。指针指向内存中该对象的第一个字节的地址,即对象开始的位置。对象占用多少个后续字节取决于与指针关联的类型。

这是它在记忆中的样子:

                    0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F           
00000001'0020000x: (38 00 20 00 01 00 00 00) 55 23 0A 25 00 43 2F 10
00000001'0020001x:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
00000001'0020002x:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00
00000001'0020003x:  13 37 D0 0C 00 00 00 00 [02 B0 AD 1B EF BE AD DE
00000001'0020004x:  1A 00 0F F0 0D D0 01 C0] 00 00 00 00 00 00 00 00

地址 0x00000001'00200000 包含一个指向两个 64 位整数结构的指针(我用圆括号标记了它的内存区域)。它的第一个字节是 38(最低有效字节),然后是 00、20、00、01,还有三个 00(最后一个是最高有效字节),所以它们代表数字 0x00000001'00200038,这是对象指向的内存起始地址。指针后面还有一些字节,但它们无关紧要,它们是其他数据的一部分。

现在让我们看看指针中包含的地址是什么:0x00000001'00200038。该区域的第一个字节是 02,然后是 B0,下一个是 AD,然后是 1B,依此类推……应该有两个 64 位整数打包在一个结构体中,因此指向的对象有 16 个字节长(我用方括号标记其内存区域)。第一个整数是 0xDEADBEEF1BADB002,第二个整数是 0xC001D00DF00F001A。

换句话说,我们有以下情况:

typedef struct {
   int first, second;
} TwoInts;

TwoInts *ptr;

TwoInts obj = { 0xC001D00DF00F001A, 0xDEADBEEF1BADB002 };

…

ptr = &obj;

对象

obj
已分配在从地址0x00000001'00200038开始的内存中,而指针
ptr
已在从地址0x00000001'00200000开始的内存中分配,并且它包含
obj的第一个字节的地址
。像这样:

 ptr:                       obj:
 0x00000001'00200000:       0x00000001'00200038: 0x00000001'00200040: 
[0x00000001'00200038]----->[0xC001D00DF00F001A] [0xDEADBEEF1BADB002]

还要记住,当涉及到 x86-64 上的内存地址时,它们位于虚拟内存地址空间中,这意味着它们并不完全是 RAM 芯片上实际物理内存中的地址。 CPU 的内存管理单元内部正在进行地址转换,将地址从虚拟地址空间转换为 RAM 中的物理地址。当操作系统加载您的程序并开始将其作为进程运行时,它会为其分配一些内存页并建立从虚拟地址空间到物理内存的映射。因此,从程序的角度来看,就好像您拥有从 0 到 2^64–1 的整个地址空间可供您使用,但此地址空间的大部分映射到任何内容,并且无法由您的程序读取或写入因为它们没有任何实际记忆的支持。操作系统为您的进程分配了一些内存段,并将其映射到您可以使用的实际 RAM,并且您可以安全地读取或写入这些内存段。如果您尝试访问该范围之外的某些内存,CPU 将检测到它,引发异常,并告诉操作系统因行为不当而终止您的程序 :J 此外,您可以运行程序的多个实例,所有这些实例似乎都使用相同的内存地址,但由于它们是“虚拟的”,因此每个实例实际上都可能映射到不同的物理地址,以便实例不会覆盖每个实例别人的数据。

© www.soinside.com 2019 - 2024. All rights reserved.