c++ - 指针(技巧): Memory Reference

标签 c++ c pointers memory-management

关于C指针的一个技巧问题。阅读下面的代码片段并尝试解释列表值更改的原因(此问题基于 this 代码):

taillist的内存地址。

如何更改下面的列表

typedef struct _node {
   struct _node *next;
   int value;
}Node;


 int main(){
   Node *list, *node, *tail;
   int i = 100;

   list = NULL;
   printf("\nFirst . LIST value = %d", list);

  tail =(Node *) &list;
  node = malloc (sizeof (Node));
  node->next = NULL;
  node->value = i;

  //tail in this point contains the memory address of list
  tail->next = node;
  printf("\nFinally. LIST value = %d", list);
  printf("\nLIST->value = %d", (list->value));

return 0;

}

----输出

First . List value = 0

为什么这个值???我没想到这个......

Finally . LIST value = 16909060

LIST->value = 100

最佳答案

让我们看看程序中的内存发生了什么。您从 3 个局部变量开始,所有变量都是 Node* 类型。目前它们都指向垃圾,因为它们已被声明但尚未初始化。

内存的 ASCII 艺术图可能是(布局取决于实现)

      list   node   tail
  --------------------------
... | 0xFE | 0x34 | 0xA3 | ...
  --------------------------

然后,您将 list 设置为 NULL,并将 tail 设置为节点的地址(抛弃它的类型,这是一个坏主意),给您

      list   node   tail
  --------------------------
... | NULL | 0xFE | &list | ...
  --------------------------
        ^             |
        +-------------+

然后您 malloc 一个新的 Node,并将 list 设置为其地址。

      list    node   tail          next  value
  ---------------------------  ------------------
... | NULL | &next | &list | ... | NULL | 100 | ...
  ---------------------------  ------------------
        ^      |       |             ^
        |      +---------------------+
        +--------------+

接下来尝试将 tail->next 设置为节点。您已经说过,当您进行类型转换时,您知道 tail 指向 Node,因此编译器相信您。 Node 尾部指向从 list 的地址开始,如下所示

     tail                                list
     next    value                       next   value
  ----------------------------------  ------------------
... | NULL | &list->next | &list | ... | NULL | 100 | ...
  ----------------------------------  ------------------

然后将 tail->next 设置为 node,使 listnode 都指向 列表结构。

      list    node   tail          next  value
   ---------------------------  ------------------
... | &next | &next | &list | ... | NULL | 100 | ...
   ---------------------------  ------------------
       | ^     |       |             ^
       | |     +---------------------|
       | +-------------+             |
       +-----------------------------+

您已将 list 打印为有符号整数(“%d”)。这是一个坏主意 - 如果您使用 64 位机器并且 printf 语句中有其他参数,它们可能会被破坏,请改用指针格式(“%p”)。 list->valuenode->value 相同,因此它仍然是 100

如果您考虑一下指针在机器中的实际表示方式,那么指针就会变得更容易 - 作为一个包含所有数据(模指针大小、虚拟内存等)的巨大数组的索引。

下次使用list = node可能会更容易。

关于c++ - 指针(技巧): Memory Reference,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3658420/

相关文章:

c++ - OpenCV 如何输入 RGB 图像

c++ - 在 C++ : strange performance issue 中读取文件的奇特方式

c - 如何在c中的另一个函数之前和之后执行公共(public)代码?

python - 创建共享内存的 pythonic 对象

C 程序制作完全数列表

c++ - Vista 和 FindFirstFileEx(..., FIND_FIRST_EX_LARGE_FETCH)

c++ - VSCode 配置语法突出显示以匹配样式指南

c - 在 DOS 模式下实现消息信号中断

c - 链接 C/Rust "Hello world"时出错:未定义对 `std::io::stdio::_print 的引用

c - 以下处理指针的代码有什么问题?