C语言 为什么结构和next的地址不相同


#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 mallocn");
printf("naddress of node is: %p",hi);
printf("naddress of next is: %p",hi->next);
return 0;
}

输出为:

malloc前

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

为什么两者不相同?

TL;DR

你的代码引发未定义行为,正如Morlacke的回答中已经提到的。除此之外,你似乎在理解指针的工作方式上有问题。参考资料中的教程。


首先,从你的评论

当你说有内存分配给ip在这种情况下:

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

结果是:

  1. 您声明了一个名为iint变量并将值10赋给它。在这里,计算机在堆栈上为这个变量分配内存。比如地址0x1000。所以现在地址0x1000有内容10
  2. 然后声明一个名为ip的指针,类型为int。计算机为指针分配内存。(这很重要,见下文解释)。你的指针在地址,比如,0x2000
  3. 当你分配ip = &i时,你是在分配变量i地址到变量ip。现在变量ip(指针)的地址是i的地址。ip不包含10-i的值。把这个赋值看作ip = 0x1000(实际上不写这个代码)。
  4. 要使用指针获得值10,您必须执行*ip-这称为指针解引用。当你这样做时,计算机将访问指针所保存的地址的内容。在这种情况下,计算机将访问i地址上的内容,即10。可以这样想:get the contents of address 0x1000

这段代码之后的内存是这样的:

VALUE    :   10    | 0x1000 |
VARIABLE :    i    |   ip   |
ADDRESS  :  0x1000 | 0x2000 |

指针指针是c语言中的一种特殊类型的变量。你可以把指针看作是类型化变量,其中保存地址. 你的计算机在堆栈上为指针分配的空间取决于你的架构-在32bit机器上,指针将占用4字节;在64bit机器上,指针占用8字节。只有计算机为指针()分配的内存有足够的空间存储地址) .

然而,指针保存着内存地址,所以你可以让它指向某个内存块…比如从malloc返回的内存块.


因此,记住这一点,让我们看看你的代码:

NODE *hi;   
printf("nbefore mallocn");
printf("naddress of node is: %p",hi);
printf("naddress of next is: %p",hi->next);
  1. 声明一个指向NODE的指针称为hi。假设变量hi的地址是0x1000,而该地址的内容是是任意的——你没有初始化它,所以它可以是从0到a的任何值。。
  2. 然后,当您在printf中打印hi时,您正在打印该地址0x1000的内容…但你不知道里面有什么……然后取消对hi变量的引用。你告诉计算机:访问ThunderCat的内容并打印变量next的值. 现在,我不知道ThunderCats内部是否有变量,也不知道它们是否喜欢被访问……这是未定义行为。而且很糟糕!

修改:

NODE *hi = malloc(sizeof NODE);
printf("&hi: %pn", &hi);
printf(" hi: %pn", 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)   : %pn", &hi);
printf("Contents of hi        : %pn", hi);
printf("Address of next(&next): %pn", &(hi->next));
printf("Contents of next      : %pn", hi->next);
printf("Address of id         : %pn", &(hi->id));
printf("Contents of id        : %dn", hi->id);
free(hi);
return 0;
}

输出:

$ ./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

变量hi的地址是1,它指向的地址是是另一回事。在这个输出中有几点需要注意:

  1. hi在栈上。它所指向的块在堆上。
  2. id的地址与内存块相同(因为它是结构的第一个元素)。
  3. next的地址从id的8个字节,当它应该只有4(毕竟int只有4个字节长)-这是由于内存对齐。
  4. next的内容是hi所指向的同一块。
  5. hi指针本身"分配"的内存量是8字节,因为我正在64bit上工作。这就是它所拥有和需要的空间
  6. 总是在malloc之后的free。避免内存泄漏
  7. 永远不要为了学习以外的目的而写这样的代码。

注意:当我说"分配给指针的内存"时,我的意思是当堆栈框架设置后声明指针时,计算机在堆栈上为它分隔的空间。

引用

  • SO:如何定义未定义行为
  • SO:我是否转换malloc的结果
  • SO:堆栈和堆是什么,在哪里?
  • 指针基础
  • 指针算术
  • C -内存管理
  • 内存:堆栈vs堆
  • 内存管理
  • C结构包装的失落艺术将告诉你关于结构,对齐,包装等…

这里没有malloc。Hi指针指向未定义的东西。Hi ->下一个相同。

关于这个问题。为什么呢?

我认为你不理解指针。

因为next是指针类型,它指向0x7ffd37e9a470。如果输出地址If next &(hi->next),可以看到hi和hi->next的差值都是2(因为int id是第一个元素)。

相关内容

  • 没有找到相关文章

最新更新