为什么structure和next的地址不一样?
Why the address of structure and next is not same?
#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
为什么两者不一样?
你这里没有malloc。
hi 指针指向未定义的内容。
嗨->下一个一样。
关于问题。为什么他们应该是?
我觉得你不懂指针。
TL;DR
您的代码引发了 未定义的行为,正如 中已经提到的那样。除此之外,您似乎在理解指针的工作方式方面遇到了问题。请参阅教程参考资料。
首先,来自您的评论
在这种情况下,当您说为 ip
分配了内存时:
int i = 10;
int *ip;
ip = &i;
发生的情况是:
- 您声明了一个名为
i
的 int
变量,并将值 10
赋给它。这里,计算机在栈上为这个变量分配了内存。比如说,地址 0x1000
。所以现在,地址 0x1000
有内容 10
.
- 然后声明一个名为
ip
的指针,类型为 int
。计算机为指针分配内存。 (这很重要,请参阅下面的解释)。您的指针位于地址 0x2000
.
- 当您分配
ip = &i
时,您将变量 i
的 地址分配给变量 ip
。现在变量ip
(你的指针)的值是i
的地址。 ip
不包含值 10
- i
包含。将此赋值视为 ip = 0x1000
(实际上不要编写此代码)。
- 要使用您的指针获取值
10
,您必须执行 *ip
- 这称为取消引用指针。当你这样做时,计算机将访问指针所在地址的内容,在这种情况下,计算机将访问i
地址上的内容,这是 10
。将其视为:get the contents of address 0x1000
.
在那段代码之后,内存看起来像这样:
VALUE : 10 | 0x1000 |
VARIABLE : i | ip |
ADDRESS : 0x1000 | 0x2000 |
指针
指针是 C 中的一种特殊类型的变量。您可以将指针视为保存地址 的类型化变量。 space 您的计算机在堆栈上分配的指针取决于您的 体系结构 - 在 32bit
机器上,指针将占用 4 个字节;在 64bit
机器上,指针将占用 8 个字节。那是您的计算机为您的指针分配的唯一内存(足够的空间来存储地址)。
但是,指针保存内存地址,因此您可以使它指向某个内存块...就像从 malloc 返回的内存块一样。
所以,考虑到这一点,让我们看看您的代码:
NODE *hi;
printf("\nbefore malloc\n");
printf("\naddress of node is: %p",hi);
printf("\naddress of next is: %p",hi->next);
- 声明一个指向
NODE
的指针,名为 hi
。让我们想象这个变量 hi
有地址 0x1000
,并且那个地址 的 内容是任意的——你没有初始化它,所以它可以是从零开始的任何东西ThunderCat.
- 然后,当您在
printf
中打印 hi
时,您正在打印该地址 0x1000
的内容...但是您不知道那里有什么.. . 可以是任何东西。
- 然后取消引用
hi
变量。你告诉计算机:访问 ThunderCat 的内容并打印变量 next
的值。现在,我不知道 ThunderCats 内部是否有变量,也不知道它们是否愿意被访问...所以这是 未定义的行为。而且不好!
要解决这个问题:
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;
}
并且输出:
$ ./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
的地址与内存块相同(那是因为它是结构的第一个元素)。
next
的地址距离id
有8个字节,而它应该只有4个(毕竟int
只有4个字节长)——这是内存的原因结盟。
next
的内容与hi
所指向的块相同。
hi
指针本身的内存量 "alloced" 是 8 个字节,因为我正在处理 64bit
。这就是它拥有和需要的所有房间。
- 在
malloc
之后总是 free
。避免 memory leaks
- 除了学习之外,不要为了其他目的而编写这样的代码。
注意:当我说 "memory alloced for the pointer" 时,我的意思是 space 当声明发生在 Stack Frame 设置之后时,计算机在堆栈上为它分离。
参考资料
- 所以:How Undefined is Undefined Behavior
- 所以:Do I cast the result of malloc
- 所以:What and where are the stack and heap?
- Pointer Basics
- Pointer Arithmetic
- C - Memory Management
- Memory: Stack vs Heap
- Memory Management
- The Lost Art of C Strucutre Packing 会告诉您有关结构、对齐、打包等...
因为next是指针类型,指向0x7ffd37e9a470。
如果打印 if next &(hi->next) 的地址,可以看到 hi 和 hi->next 都相差 2(因为 int id 是第一个元素)。
#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
为什么两者不一样?
你这里没有malloc。 hi 指针指向未定义的内容。 嗨->下一个一样。
关于问题。为什么他们应该是?
我觉得你不懂指针。
TL;DR
您的代码引发了 未定义的行为,正如
首先,来自您的评论
在这种情况下,当您说为 ip
分配了内存时:
int i = 10;
int *ip;
ip = &i;
发生的情况是:
- 您声明了一个名为
i
的int
变量,并将值10
赋给它。这里,计算机在栈上为这个变量分配了内存。比如说,地址0x1000
。所以现在,地址0x1000
有内容10
. - 然后声明一个名为
ip
的指针,类型为int
。计算机为指针分配内存。 (这很重要,请参阅下面的解释)。您的指针位于地址0x2000
. - 当您分配
ip = &i
时,您将变量i
的 地址分配给变量ip
。现在变量ip
(你的指针)的值是i
的地址。ip
不包含值10
-i
包含。将此赋值视为ip = 0x1000
(实际上不要编写此代码)。 - 要使用您的指针获取值
10
,您必须执行*ip
- 这称为取消引用指针。当你这样做时,计算机将访问指针所在地址的内容,在这种情况下,计算机将访问i
地址上的内容,这是10
。将其视为:get the contents of address 0x1000
.
在那段代码之后,内存看起来像这样:
VALUE : 10 | 0x1000 |
VARIABLE : i | ip |
ADDRESS : 0x1000 | 0x2000 |
指针
指针是 C 中的一种特殊类型的变量。您可以将指针视为保存地址 的类型化变量。 space 您的计算机在堆栈上分配的指针取决于您的 体系结构 - 在 32bit
机器上,指针将占用 4 个字节;在 64bit
机器上,指针将占用 8 个字节。那是您的计算机为您的指针分配的唯一内存(足够的空间来存储地址)。
但是,指针保存内存地址,因此您可以使它指向某个内存块...就像从 malloc 返回的内存块一样。
所以,考虑到这一点,让我们看看您的代码:
NODE *hi;
printf("\nbefore malloc\n");
printf("\naddress of node is: %p",hi);
printf("\naddress of next is: %p",hi->next);
- 声明一个指向
NODE
的指针,名为hi
。让我们想象这个变量hi
有地址0x1000
,并且那个地址 的 内容是任意的——你没有初始化它,所以它可以是从零开始的任何东西ThunderCat. - 然后,当您在
printf
中打印hi
时,您正在打印该地址0x1000
的内容...但是您不知道那里有什么.. . 可以是任何东西。 - 然后取消引用
hi
变量。你告诉计算机:访问 ThunderCat 的内容并打印变量next
的值。现在,我不知道 ThunderCats 内部是否有变量,也不知道它们是否愿意被访问...所以这是 未定义的行为。而且不好!
要解决这个问题:
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;
}
并且输出:
$ ./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
的地址与内存块相同(那是因为它是结构的第一个元素)。next
的地址距离id
有8个字节,而它应该只有4个(毕竟int
只有4个字节长)——这是内存的原因结盟。next
的内容与hi
所指向的块相同。hi
指针本身的内存量 "alloced" 是 8 个字节,因为我正在处理64bit
。这就是它拥有和需要的所有房间。- 在
malloc
之后总是free
。避免 memory leaks - 除了学习之外,不要为了其他目的而编写这样的代码。
注意:当我说 "memory alloced for the pointer" 时,我的意思是 space 当声明发生在 Stack Frame 设置之后时,计算机在堆栈上为它分离。
参考资料
- 所以:How Undefined is Undefined Behavior
- 所以:Do I cast the result of malloc
- 所以:What and where are the stack and heap?
- Pointer Basics
- Pointer Arithmetic
- C - Memory Management
- Memory: Stack vs Heap
- Memory Management
- The Lost Art of C Strucutre Packing 会告诉您有关结构、对齐、打包等...
因为next是指针类型,指向0x7ffd37e9a470。 如果打印 if next &(hi->next) 的地址,可以看到 hi 和 hi->next 都相差 2(因为 int id 是第一个元素)。