C中的指针寻址

时间:2016-06-11 21:54:10

标签: c pointers memory

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

以下代码创建一个包含四个小整数的数组,然后逐字节地遍历保存它们的内存地址。看起来整数存储在0字节中,随机值存储在字节1-3中:

        int ia[] = {1, 3, 4, 7};

    printf("Address of Int Array 0 is: %p\n", &ia[0]);
    printf("Address of Int Array 1 is: %p\n", &ia[1]);
    printf("Address of Int Array 2 is: %p\n", &ia[2]);
    printf("Address of Int Array 3 is: %p\n", &ia[3]);

    void *addr = (void *) &ia[0];

    printf("\nAddress: %p\n", addr);
    printf("Data:  %d\n", *((int*) addr));

    addr = addr+1;

    printf("\nAddress: %p\n", addr);
    printf("Data:  %d\n", *((int*) addr));

    addr = addr+1;

    printf("\nAddress: %p\n", addr);
    printf("Data:  %d\n", *((int*) addr));

    addr = addr+1;

    printf("\nAddress: %p\n", addr);
    printf("Data:  %d\n", *((int*) addr));

    addr = addr+1;

    printf("\nAddress: %p\n", addr);
    printf("Data:  %d\n", *((int*) addr));

    addr = addr+4;

    printf("\nAddress: %p\n", addr);
    printf("Data:  %d\n", *((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: %p\n", &ia[0]);
printf("Address of Int Array 1 is: %p\n", &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个字节,依此类推 - 特别是如果返回的数据小于机器的字大小?

2 个答案:

答案 0 :(得分:2)

  

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

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

p+1始终评估p之后的下一个对象的地址;如果对象的大小是4个字节,则p+1p的值加4。如果对象的大小为64字节,则p+1将值p加64。

答案 1 :(得分:1)

  

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

你没有把问题弄得太清楚,但这似乎是你感到困惑的事情。首先,您的代码需要一些工作:如果您正在进行逐字节迭代,请考虑使用char指针。 C中的void指针不应该用于算术。只是为了挑剔,使用循环来避免重写/复制粘贴一切。 Here是一些应该清除的代码,请务必阅读输出。

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

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

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