为什么结构的地址和下一个不一样?

时间:2015-09-25 10:46:16

标签: c malloc dynamic-memory-allocation

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

struct node
{
    int id;
    struct node *next;
};
typedef struct node NODE;
int main()
{
    NODE *hi;   
    printf("\nbefore malloc\n");
    printf("\naddress of node is: %p",hi);
    printf("\naddress of next is: %p",hi->next);
return 0;
}

输出结果为:

在malloc之前

节点的地址是:0x7ffd37e99e90 下一个地址是:0x7ffd37e9a470

为什么两者不相同?

3 个答案:

答案 0 :(得分:3)

TL; DR

您的代码会引发未定义的行为,如Morlacke's Answer中已提到的那样。除此之外,似乎你在理解指针如何工作方面遇到了问题。请参阅参考资料。

首先,来自您的评论

当你说在这种情况下为ip分配了内存时:

int i = 10;
int *ip;
ip = &i;

会发生什么:

  1. 您声明了一个名为int的{​​{1}}变量,并为其指定了值i。在这里,计算机为堆栈上的此变量分配内存。说,地址10。现在,地址0x1000的内容为0x1000
  2. 然后声明一个名为10的指针,其类型为ip。计算机为指针分配内存。 (这很重要,请参阅下面的解释)。您的指针位于地址,例如int
  3. 当您指定0x2000时,您将变量ip = &i地址指定给变量i。现在,变量ip(您的指针)的ip的地址。 i不会保留值ip - 10。将此作业视为i实际上并未编写此代码)。
  4. 要使用指针获取值ip = 0x1000,您必须执行10 - 这称为取消引用指针。当你这样做时,计算机将访问指针所占地址的内容,在这种情况下,计算机将访问地址*ip上的内容,即{{ 1}}。可以将其视为: i
  5. 在代码片段之后,内存看起来像这样:

    10

    指针

    指针是C中特殊类型的变量。您可以将指针视为保存地址的类型变量。您的计算机在堆栈上为指针分配的空间取决于您的体系结构 - 在get the contents of address 0x1000计算机上,指针将占用4个字节;在VALUE : 10 | 0x1000 | VARIABLE : i | ip | ADDRESS : 0x1000 | 0x2000 | 机器上,指针将占用8个字节。这是您的计算机为您的指针分配的唯一内存(足够的空间来存储地址)。

    但是,指针保存内存地址,因此您可以指向某个内存块...就像从 malloc 返回的内存块一样。

    因此,考虑到这一点,让我们看看您的代码:

    32bit
    1. 声明指向64bit NODE *hi; printf("\nbefore malloc\n"); printf("\naddress of node is: %p",hi); printf("\naddress of next is: %p",hi->next); 的指针。让我们假设这个变量NODE的地址为hi,而该地址的内容是任意的 - 你没有初始化它,所以它可以是从零到<强> ThunderCat 即可。
    2. 然后,当您在hi中打印0x1000时,您正在打印该地址的内容hi ...但您不知道那里有什么......它可能是什么。
    3. 然后取消引用printf变量。您告诉计算机:访问 ThunderCat 的内容并打印变量0x1000 的值。现在,我不知道ThunderCats中是否有变量,也不知道他们是否愿意访问...所以这是 Undefined Behavior 。而且不好!
    4. 解决这个问题:

      hi

      现在你有一个结构大小的内存块来保存一些数据。但是,您仍然没有初始化它,因此访问它的内容是仍未定义的行为

      要初始化它,您可以:

      next

      现在你可以打印任何你想要的东西。见:

      NODE *hi = malloc(sizeof NODE);
      printf("&hi: %p\n", &hi);
      printf(" hi: %p\n", hi);
      

      输出:

      hi->id = 10;
      hi->next = hi;
      

      变量#include <stdio.h> #include <stdlib.h> struct node { int id; struct node *next; }; typedef struct node NODE; int main(void) { NODE *hi = malloc(sizeof(NODE)); if (!hi) return 0; hi->id = 10; hi->next = hi; printf("Address of hi (&hi) : %p\n", &hi); printf("Contents of hi : %p\n", hi); printf("Address of next(&next): %p\n", &(hi->next)); printf("Contents of next : %p\n", hi->next); printf("Address of id : %p\n", &(hi->id)); printf("Contents of id : %d\n", hi->id); free(hi); return 0; } 的地址是1,而指向的地址是另一个。这个输出有几点需要注意:

      1. $ ./draft Address of hi (&hi) : 0x7fffc463cb78 Contents of hi : 0x125b010 Address of next(&next): 0x125b018 Contents of next : 0x125b010 Address of id : 0x125b010 Contents of id : 10 在堆栈中。它指向的块在堆上。
      2. hi的地址与内存块相同(因为它是结构的第一个元素)。
      3. hi的地址是id的8个字节,当它应该只有4个(在所有next之后只有4个字节长) - 这是由于内存对齐。
      4. id的内容与int指向的块相同。
      5. next指针本身“分配”的内存量为8个字节,因为我正在处理hi。这就是它拥有的所有房间
      6. hi之后始终64bit。避免使用memory leaks
      7. 永远不要将此类代码用于除学习之外的其他目的。
      8. 注意:当我说“为指针分配的内存”时,我指的是在Stack Frame设置之后声明发生时计算机在堆栈上分离的空间。

        参考

答案 1 :(得分:1)

你这里没有malloc。 嗨指针指向未定义的东西。 hi->接下来就是这样。

关于这个问题。为什么他们应该?

我认为你不明白指针。

答案 2 :(得分:-1)

因为next是一个指针类型,它指向0x7ffd37e9a470。 如果您打印地址如果下一个&amp;(hi->下一个),您可以看到hi和hi-&gt; next的差值为2(因为int id是第一个元素)。