#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
为什么两者不相同?
答案 0 :(得分:3)
您的代码会引发未定义的行为,如Morlacke's Answer中已提到的那样。除此之外,似乎你在理解指针如何工作方面遇到了问题。请参阅参考资料。
当你说在这种情况下为ip
分配了内存时:
int i = 10;
int *ip;
ip = &i;
会发生什么:
int
的{{1}}变量,并为其指定了值i
。在这里,计算机为堆栈上的此变量分配内存。说,地址10
。现在,地址0x1000
的内容为0x1000
。10
的指针,其类型为ip
。计算机为指针分配内存。 (这很重要,请参阅下面的解释)。您的指针位于地址,例如int
。0x2000
时,您将变量ip = &i
的地址指定给变量i
。现在,变量ip
(您的指针)的值是ip
的地址。 i
不会保留值ip
- 10
。将此作业视为i
(实际上并未编写此代码)。ip = 0x1000
,您必须执行10
- 这称为取消引用指针。当你这样做时,计算机将访问指针所占地址的内容,在这种情况下,计算机将访问地址*ip
上的内容,即{{ 1}}。可以将其视为: i
。在代码片段之后,内存看起来像这样:
10
指针是C中特殊类型的变量。您可以将指针视为保存地址的类型变量。您的计算机在堆栈上为指针分配的空间取决于您的体系结构 - 在get the contents of address 0x1000
计算机上,指针将占用4个字节;在VALUE : 10 | 0x1000 |
VARIABLE : i | ip |
ADDRESS : 0x1000 | 0x2000 |
机器上,指针将占用8个字节。这是您的计算机为您的指针分配的唯一内存(足够的空间来存储地址)。
但是,指针保存内存地址,因此您可以指向某个内存块...就像从 malloc 返回的内存块一样。
因此,考虑到这一点,让我们看看您的代码:
32bit
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 即可。hi
中打印0x1000
时,您正在打印该地址的内容hi
...但您不知道那里有什么......它可能是什么。printf
变量。您告诉计算机:访问 ThunderCat 的内容并打印变量0x1000
的值。现在,我不知道ThunderCats中是否有变量,也不知道他们是否愿意访问...所以这是 Undefined Behavior 。而且不好! 解决这个问题:
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,而指向的地址是另一个。这个输出有几点需要注意:
$ ./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
的地址与内存块相同(因为它是结构的第一个元素)。 hi
的地址是id
的8个字节,当它应该只有4个(在所有next
之后只有4个字节长) - 这是由于内存对齐。 id
的内容与int
指向的块相同。next
指针本身“分配”的内存量为8个字节,因为我正在处理hi
。这就是它拥有的所有房间。hi
之后始终64bit
。避免使用memory leaks 注意:当我说“为指针分配的内存”时,我指的是在Stack Frame设置之后声明发生时计算机在堆栈上分离的空间。
答案 1 :(得分:1)
你这里没有malloc。 嗨指针指向未定义的东西。 hi->接下来就是这样。
关于这个问题。为什么他们应该?
我认为你不明白指针。
答案 2 :(得分:-1)
因为next是一个指针类型,它指向0x7ffd37e9a470。 如果您打印地址如果下一个&amp;(hi->下一个),您可以看到hi和hi-&gt; next的差值为2(因为int id是第一个元素)。