【问题标题】:why there is difference in address but still pointing to the same data?为什么地址不同但仍然指向相同的数据?
【发布时间】:2020-09-22 04:08:43
【问题描述】:
#include<stdio.h>

#include<stdlib.h>

#include<string.h>

struct node {
  int data;
  struct node * next;
};

int main() {

  struct node * head = (struct node * ) malloc(sizeof(struct node));
  head -> data = 10;

  head -> next = (struct node * ) malloc(sizeof(struct node));
  head -> next -> data = 20;

  head -> next -> next = NULL;

  int noOfNodes = 2;

  char * buff = malloc(50);

  strncpy(buff, (char * ) & noOfNodes, sizeof(int));
  // strncpy(buff+4,(char *)head,sizeof(struct node *));
  memcpy(buff + 4, (char * ) head, sizeof(struct node * ));

  printf("noOfNodes: %d\n\n", *(int * ) buff);

  printf("1]<%p><%d>\n", head, head -> data);
  printf("2]<%p><%d>\n\n", ((struct node * ) buff + 4), ((struct node * )(buff + 4)) -> data);

  printf("address of next node \n");

  printf("3]<%p>\n", head -> next);
  printf("4]<%p>\n", ((struct node * )(buff + 4)) -> next);

  return 0;
}

输出:

noOfNodes: 2

1]<0x56450bd632a0><10>
2]<0x56450bd63320><10>

address of next node 
3]<0x56450bd632c0>
4]<(nil)>

为什么地址不同?

1] 以 ...2a0 结尾

2] 以 ...320 结尾

如果地址不同,那么它如何正确指向变量 data(...->data) ?

为什么是 (buff+4)->next 是 NULL?它应该与 head->next 相同(即 )。

struct node *n1 = head; 

当我们这样做时,无论结构节点有多大,这只需要 8 个字节来存储(因为我们正在存储结构节点的地址)。

我想使用memcpy()(仅使用 8 个字节)存储struct node head 的地址而不是所有struct node 的地址(buff+4)。 这个怎么做 ?这就是我使用 (struct node *) 的原因。

【问题讨论】:

    标签: c pointers struct


    【解决方案1】:

    [tl;dr] 要将整个 *head 复制到 buff+4 memcpy 行需要进行如下更改。

    memcpy(buff+4, (char *)head, sizeof(struct node));  // instead of sizeof(struct node *)
    

    使用 OP 的代码,假设可能的情况是 32b 整数和 64b 指针:

    • struct node 被填充以满足指针对齐要求

      struct node
      {
      int data;
      int hidden_padding_field;  // <--- inserted by the compiler
      struct node *next;
      };
      
    • 以下内容从head复制8个字节到buff+4,意思是head-&gt;datahidden_padding_field被复制,但head-&gt;next没有。

      memcpy(buff+4, (char *)head, sizeof(struct node *));
      

    因此,data 值被正确复制,但 next 指针未初始化。它恰好是 NULL 完全是偶然的,只是未定义行为的一种可能表现。

    【讨论】:

    • 谢谢,现在两个.... ->下一个是一样的。 OP的代码是什么?
    • @temp1284 那是你的代码。这里的“OP”代表“原始海报”,有时也代表“原始帖子”。
    • @temp1284 要复制head 指针,请使用memcpy(buff+4, &amp;head, sizeof(struct node *));
    • head 有一个类型 (struct node *),当我们说 head 时,它表示 (struct node) 的地址,&amp;head 表示指针的地址 (struct node *)。我想要的是struct node的地址,即head(不是&amp;head);
    • @temp1284 你在我上一条评论中得到的head指向的struct node的地址。 head 是一个指针变量,它的值是struct node 的地址,而该值存储在地址&amp;head 中。所以memcpy(buff+4, &amp;head, sizeof(struct node *)); 将把head 的值复制到buff+4,这是struct nodemalloc 的地址。
    【解决方案2】:

    为什么地址不同?

    因为buff 数组与malloc 用于head 的数组是不同的内存块,所以buff+4 在内存中是不同的位置。

    如果地址不同,那么它如何正确指向变量 data(...->data) ?

    因为您memcpyd 将一些内存放入该位置的buff,从head 指向的内存中复制它。所以虽然是不同的内存块,但是写入的数据是一样的。

    为什么是(buff+4)->next是NULL?

    因为你没有复制足够的内存,所以next成员应该在的部分仍然是复制之前buff的那个部分。发生这种情况是因为您告诉memcpy 复制与struct node * 占用的内存一样多的内存;但是您不想复制一块作为指针的内存,您想复制一块作为节点本身的内存。所以应该说sizeof(struct node)而不是sizeof(struct node *)

    struct node 结构以int data 开头,而int 可能与任何普通指针的大小相同(至少,我不认为更大的任何情况)。因此,当我们查看从位置buff + 4 开始的内存时,似乎我们在那里复制了足够的数据以将正确的值放入-&gt;data,但不足以对-&gt;next 做任何事情。

    【讨论】:

      猜你喜欢
      • 2022-11-23
      • 2019-05-13
      • 2011-05-15
      • 1970-01-01
      • 1970-01-01
      • 2016-10-06
      • 1970-01-01
      • 2018-11-08
      • 1970-01-01
      相关资源
      最近更新 更多