问题描述
#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
address of node is: 0x7ffd37e99e90address of next is: 0x7ffd37e9a470
为什么两者都不相同?
推荐答案
TL; DR
您的代码会引发未定义行为,如 Morlacke的答案中所述.除此之外,您似乎在理解指针的工作方式上遇到了问题.请参阅参考资料以获取教程.
TL;DR
Your code provokes Undefined Behavior, as already mentioned in Morlacke's Answer. Other than that, it seems that you're having problems on understanding how pointers work. See references for tutorials.
在这种情况下,当您说为ip
分配了内存时:
When you say that there's memory allocated for ip
in this case:
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
.
- You declare an
int
variable calledi
and assign the value10
to it. Here, the computer allocates memory for this variable on the stack. Say, at address0x1000
. So now, address0x1000
has content10
. - Then you declare a pointer called
ip
, having typeint
. The computer allocates memory for the pointer. (This is important, see bellow for explanation). Your pointer is at address, say,0x2000
. - When you assign
ip = &i
, you're assigning the address of variablei
to variableip
. Now the value of variableip
(your pointer) is the address ofi
.ip
doesn't hold the value10
-i
does. Think of this assignment asip = 0x1000
(don't actually write this code). - To get the value
10
using your pointer you'd have to do*ip
- this is called dereferencing the pointer. When you do that, the computer will access the contents of the address held by the pointer, in this case, the computer will access the contents on the address ofi
, which is10
. Think of it as:get the contents of address 0x1000
.
在这段代码片段之后,内存看起来像这样:
Memory looks like this after that snippet of code:
VALUE : 10 | 0x1000 |
VARIABLE : i | ip |
ADDRESS : 0x1000 | 0x2000 |
指针
指针是C语言中的一种特殊类型的变量.您可以将指针视为保存地址的类型化变量.您的计算机在堆栈上为指针分配的空间取决于您的体系结构-在32bit
机器上,指针将占用4个字节.在64bit
机器上,指针将占用8个字节.那是计算机为指针分配的仅内存(有足够的空间来存储地址).
Pointers
Pointers are a special type of variable in C. You can think of pointers as typed variables that hold addresses. The space your computer allocates on the stack for pointers depends on your architecture - on 32bit
machines, pointers will take 4 bytes; on 64bit
machines pointers will take 8 bytes. That's the only memory your computer allocates for your pointers (enough room to store an address).
但是,指针保存着内存地址,因此您可以使其指向某个内存块...就像从 malloc .
However, pointers hold memory addresses, so you can make it point to some block of memory... Like memory blocks returned from malloc.
因此,考虑到这一点,让我们看一下您的代码:
So, with this in mind, lets see your code:
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中是否包含变量,也不知道它们是否喜欢被访问...所以这是 Undefined Behavior .这是不好!
- Declare a pointer to
NODE
calledhi
. Lets imagine this variablehi
has address0x1000
, and the contents of that address are arbitrary - you didn't initialize it, so it can be anything from zeroes to a ThunderCat. - Then, when you print
hi
in yourprintf
you're printing the contents of that address0x1000
... But you don't know what's in there... It could be anything. - Then you dereference the
hi
variable. You tell the computer: access the contents of the ThunderCat and print the value of variablenext
. Now, I don't know if ThunderCats have variables inside of them, nor if they like to be accessed... so this is Undefined Behavior. And it's bad!
要解决此问题:
NODE *hi = malloc(sizeof NODE);
printf("&hi: %p\n", &hi);
printf(" hi: %p\n", hi);
现在,您有一个结构大小的存储块来保存一些数据.但是,您仍然没有初始化它,因此访问它的内容仍然是未定义的行为.
Now you have a memory block of the size of your structure to hold some data. However, you still didn't initialize it, so accessing the contents of it is still undefined behavior.
要初始化它,您可以执行以下操作:
To initialize it, you may do:
hi->id = 10;
hi->next = hi;
现在您可以打印任何内容.看到这个:
And now you may print anything you want. See this:
#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
的地址是一个,而其指向的地址是另一个.在此输出上有几件事要注意:
The address of variable hi
is one, and the address to which it points to is another. There are several things to notice on this output:
-
hi
在堆栈中.它指向的块在堆上. -
id
的地址与内存块相同(这是因为它是结构的第一个元素). -
next
的地址是id
的8个字节,当它应该仅为4个(所有int
仅4个字节长)时–这是由于内存对齐. -
next
的内容与hi
指向的块相同. - 为
hi
指针本身分配"的内存量为8个字节,因为我正在使用64bit
.这就是它拥有和需要的所有房间. - 在
malloc
之后总是free
.避免内存泄漏 - 除了学习之外,请勿将这样的代码用于其他目的.
hi
is on the stack. The block to which it points is on the heap.- The address of
id
is the same as the memory block (that's because it's the first element of the structure). - The address of
next
is 8 bytes fromid
, when it should be only 4(after allint
s are only 4 bytes long) - this is due to memory alignment. - The contents of
next
is the same block pointed byhi
. - The amount of memory "alloced" for the
hi
pointer itself is 8 bytes, as I'm working on a64bit
. That's all the room it has and needs. - Always
free
after amalloc
. Avoid memory leaks - Never write code like this for other purposes than learning.
注意:当我说为指针分配的内存"时,是指在堆栈框架设置.
- SO:未定义行为如何未定义
- SO:我是否强制转换malloc的结果
- SO:什么是堆栈和堆?在哪里?
- 指针基础
- 指针算术
- C-内存管理
- 内存:堆栈与堆
- 内存管理
- C型钢包装的失落艺术会告诉您有关结构,对齐方式的信息,包装等...
- SO: How Undefined is Undefined Behavior
- SO: Do I cast the result of malloc
- SO: 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 will tell you about structures, alignment, packing, etc...
这篇关于为什么结构和下一个的地址不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!