本文介绍了为什么结构和下一个的地址不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#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;

会发生什么:

  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 .
  1. You declare an int variable called i and assign the value 10 to it. Here, the computer allocates memory for this variable on the stack. Say, at address 0x1000. So now, address 0x1000 has content 10.
  2. Then you declare a pointer called ip, having type int. The computer allocates memory for the pointer. (This is important, see bellow for explanation). Your pointer is at address, say, 0x2000.
  3. When you assign ip = &i, you're assigning the address of variable i to variable ip. Now the value of variable ip (your pointer) is the address of i. ip doesn't hold the value 10 - i does. Think of this assignment as ip = 0x1000 (don't actually write this code).
  4. 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 of i, which is 10. 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);
  1. 声明一个指向NODE的指针,称为hi.假设此变量hi的地址为0x1000,并且该地址的内容是任意的-您没有初始化它,因此它可以是从零到 ThunderCat .
  2. 然后,当您在printf中打印hi时,您正在打印该地址0x1000的内容...但是您不知道其中的内容...可能是任何东西.
  3. 然后取消引用hi变量.您告诉计算机:访问 ThunderCat 的内容,并打印变量next 的值.现在,我不知道ThunderCats中是否包含变量,也不知道它们是否喜欢被访问...所以这是 Undefined Behavior .这是不好!
  1. Declare a pointer to NODE called hi. Lets imagine this variable hi has address 0x1000, and the contents of that address are arbitrary - you didn't initialize it, so it can be anything from zeroes to a ThunderCat.
  2. Then, when you print hi in your printf you're printing the contents of that address 0x1000... But you don't know what's in there... It could be anything.
  3. Then you dereference the hi variable. You tell the computer: access the contents of the ThunderCat and print the value of variable next. 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:

  1. hi在堆栈中.它指向的块在堆上.
  2. id的地址与内存块相同(这是因为它是结构的第一个元素).
  3. next的地址是id的8个字节,当它应该仅为4个(所有int仅4个字节长)时–这是由于内存对齐.
  4. next的内容与hi指向的块相同.
  5. hi指针本身分配"的内存量为8个字节,因为我正在使用64bit.这就是它拥有和需要的所有房间.
  6. malloc之后总是free.避免内存泄漏
  7. 除了学习之外,请勿将这样的代码用于其他目的.
  1. hi is on the stack. The block to which it points is on the heap.
  2. The address of id is the same as the memory block (that's because it's the first element of the structure).
  3. The address of next is 8 bytes from id, when it should be only 4(after all ints are only 4 bytes long) - this is due to memory alignment.
  4. The contents of next is the same block pointed by hi.
  5. The amount of memory "alloced" for the hi pointer itself is 8 bytes, as I'm working on a 64bit. That's all the room it has and needs.
  6. Always free after a malloc. Avoid memory leaks
  7. Never write code like this for other purposes than learning.

注意:当我说为指针分配的内存"时,是指在堆栈框架设置.

  • 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...

这篇关于为什么结构和下一个的地址不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 09:03