C中的指针寻址



我试图理解为什么指针的内存地址会根据数据类型增加一定数量的字节。

下面的代码创建了一个由四个小整数组成的数组,然后逐字节地遍历保存它们的内存地址。整数似乎存储在0字节中,随机值存储在1-3字节中:

int ia[] = {1, 3, 4, 7};
printf("Address of Int Array 0 is: %pn", &ia[0]);
printf("Address of Int Array 1 is: %pn", &ia[1]);
printf("Address of Int Array 2 is: %pn", &ia[2]);
printf("Address of Int Array 3 is: %pn", &ia[3]);
void *addr = (void *) &ia[0];
printf("nAddress: %pn", addr);
printf("Data:  %dn", *((int*) addr));
addr = addr+1;
printf("nAddress: %pn", addr);
printf("Data:  %dn", *((int*) addr));
addr = addr+1;
printf("nAddress: %pn", addr);
printf("Data:  %dn", *((int*) addr));
addr = addr+1;
printf("nAddress: %pn", addr);
printf("Data:  %dn", *((int*) addr));
addr = addr+1;
printf("nAddress: %pn", addr);
printf("Data:  %dn", *((int*) addr));
addr = addr+4;
printf("nAddress: %pn", addr);
printf("Data:  %dn", *((int*) addr));

输出为:

Address of Int Array 0 is: 0x7fff51b8ac30
Address of Int Array 1 is: 0x7fff51b8ac34
Address of Int Array 2 is: 0x7fff51b8ac38
Address of Int Array 3 is: 0x7fff51b8ac3c
Address: 0x7fff51b8ac30
Data:  1
Address: 0x7fff51b8ac31
Data:  50331648
Address: 0x7fff51b8ac32
Data:  196608
Address: 0x7fff51b8ac33
Data:  768
Address: 0x7fff51b8ac34
Data:  3
Address: 0x7fff51b8ac38
Data:  4

但是,当我将一个非常大的整数放入数组时,会发生以下情况:

int ia[] = {2147483647, 3, 4, 7};
printf("Address of Int Array 0 is: %pn", &ia[0]);
printf("Address of Int Array 1 is: %pn", &ia[1]);
....

输出:

Address of Int Array 0 is: 0x7fff51d1fc30
Address of Int Array 1 is: 0x7fff51d1fc34
Address of Int Array 2 is: 0x7fff51d1fc38
Address of Int Array 3 is: 0x7fff51d1fc3c
Address: 0x7fff51d1fc30
Data:  2147483647
Address: 0x7fff51d1fc31
Data:  58720255
Address: 0x7fff51d1fc32
Data:  229375
Address: 0x7fff51d1fc33
Data:  895
Address: 0x7fff51d1fc34
Data:  3
Address: 0x7fff51d1fc38
Data:  4

我认为大整数可能(尽管不太可能)会被分解成字节,四字节整数的每个内存地址一个字节,这与字节可寻址内存保持一致,字节可寻址存储器似乎是C中的表示。不过,从代码中可以看出,第一个"内存地址"只是一个实际上包含四个字节整数的结构。如果是这样的话,为什么C中的内存地址必须按数据类型的大小递增,当它看起来只是一个抽象时?地址1为什么不能返回4个字节,地址1不能返回1个字节,等等——特别是如果返回的数据小于机器的字大小?

我试图理解为什么指针的内存地址会根据数据类型增加一定数量的字节。

因为指针算术就是这样工作的;如果p是指向整数对象(int *p)的指针,则p+1将指向下一个整数对象。如果p是指向10元素整数数组(int (*p)[10])的指针,则p+1将指向下一个10元素整数阵列

p+1总是计算为p之后的下一个对象的地址;如果对象的大小是4个字节,则p+1p的值加4。如果对象的大小是64字节,则p+1将64加到p的值上。

整数存储在0字节中,随机值存储在1-3字节中

你没有把问题说得太清楚,但这似乎是你感到困惑的地方。首先,您的代码需要一些工作:如果您正在进行逐字节的迭代,请考虑使用char指针。C中的空指针不应该用于算术。为了挑剔,可以使用循环来避免重写/复制粘贴所有内容。这里有一些代码应该会澄清问题,一定要阅读输出。

C中的整数通常存储在4字节的块中(尽管根据系统架构,它可能是2或8个字节),每个字节都很重要。这意味着你所看到的这些值都不是随机的:你只是没有正确看待它们。您会在上面的代码中注意到,我修改了值的输出:

for(i = 0; i < sizeof(ia); i++)
{
printf("nAddress: %pn", addr);
printf("Data:  0x%08x == %un", *((unsigned int*) addr), *((unsigned int*) addr));
addr = addr + 1;
}

请注意,sizeof(ia)以字节为单位返回数组的大小(4个项目*4个字节,每个=16个字节),而不是数组中的元素数。%08x格式说明符将整数数据写入十六进制值,这样您就可以清楚地看到输出的每个字节。我把无符号的base10值放在它旁边,这就是你所谓的"随机数"。值0x01将转换为整数1,值0x0100将为256;通过移动一个字节,可以极大地改变值。同样值得研究endianness,它可以帮助您理解结果。

最新更新