【问题标题】:What happens to this struct pointer?这个结构指针会发生什么?
【发布时间】:2014-08-07 04:23:50
【问题描述】:

我正在使用以下代码在链表的前面推送一个新节点。我对某些概念有一些疑问。

void push(struct node **head, int data)
{
    // create a new node
    struct node *new_node;
    new_node = malloc(sizeof(struct node));

    // add data
    new_node->data = data;

    // add node to front of list
    new_node->next = *head;
    *head = new_node;
}
  1. 当我将new_node 的值分配给*head = new_node 中的*head,然后返回时,指针new_node 是否被销毁,因为它是一个自动变量?

  2. new_node 调用分配给它的内存指针在new_node 被销毁后是否仍然可以合法访问,因为它在堆上,并且从未被释放?

  3. 我们只是使用new_node 作为占位符来将地址存储到某个内存中,在完成分配和其他内容之后,我们就放手了。那么new_nodestruct node 类型是否重要,因为所有指针都只是整数,我们只是用它来存储内存地址。指针类型在哪里变得相关,即为什么我必须声明指针的数据类型以匹配指针的数据类型?

  4. 我可以将所有指针声明为整数,然后在使用前显式转换它们以匹配指针的数据类型吗?

【问题讨论】:

标签: c pointers struct dynamic-memory-allocation type-safety


【解决方案1】:

因为所有指针都是整数,我们只是用它来存储内存地址。

不!指针只是内存中的地址位置,它们的大小取决于编译器和使用的体系结构。语言不能保证它们是整数。

指针类型在哪里变得相关,即为什么我必须声明指针的数据类型以匹配被指针的数据类型?

类型安全。当你有一个指向字符的指针时,它的类型是char*,但是将它转换成一个整数指针并写入它可能会导致内存损坏。给你举个例子

char ch = 'a';
char *cp = &ch;
int *ip = (int*) cp;   // type safety lost since the pointer no longer refers to just one character
*ip = 1000;    // memory to which 1000 is written to would span beyond a character's size

当编译器看到*ip = 1000 时,它无法警告您不要出现这种损坏,因为它认为底层指针是一个整数;一个整数当然可以保存1000,因此可以很好地编译它;如果是*cp = 1000,这个值将被隐式转换为char 可持有的值,因此不会造成内存损坏。此外,如果您启用了警告,编译器将能够警告您这种缩小的隐式转换。 GCC 吐出警告:隐式常量转换溢出

我可以将所有指针声明为整数,然后在使用前显式转换它们以匹配指针的数据类型吗?

出于上述原因,您当然可以,但不能。阅读有关type safety 的更多信息。

【讨论】:

  • 有人告诉我,整数的大小等于内存的大小,因此所有内存地址都可以存储为整数。这是真的吗?
  • 不,严格来说并非如此。请参阅对您的问题的评论以获取相关帖子。
【解决方案2】:
  1. 是的。
  2. 是的。
  3. 不,您使用new_node 作为指向结构类型的指针,该结构类型有一个字段data 和另一个字段nextvoid *(或更糟的是整数)不会让你这样做。编译器需要类型信息来理解像 new_node->data = data; 这样的表达式。
  4. 当然(对于某些合适的整数类型),但为什么呢?!

【讨论】:

  • 4.只是好奇,如果我们能做到这一点,即使在理论上也是如此。
  • 如果我尝试将整数指针类型转换为结构节点,为什么整数指针比空指针更糟糕?类型转换不应该对所有数据类型均匀地工作吗?并且类型转换只是让编译器知道数据类型的一种方式,以便它可以适当地使用它吗?
  • @flipper 因为指针至少是一个指针,即它告诉代码的读者“这是某物的地址”。通常假定整数不是指针。换句话说:因为代码应该是清晰可理解的。不过,你似乎不太关心这些。 ://
【解决方案3】:

当我在 *head = new_node 中将 new_node 的值分配给 *head 时,并且 然后返回,指针 new_node 是否被销毁,因为它是 自动变量?

销毁的是分配在堆栈上的指针,但malloc的内存仍然存在(因此head是有效的)。

应该由new_node的内存指针,由malloc分配给它 在 new_node 被销毁后调用仍然是合法的,因为它是 on 堆,并且从未被释放?

它将是合法的,您可以使用它。

我们只是使用 new_node 作为占位符来存储地址 一些记忆,在我们完成任务和东西之后,我们 放手吧。那么 new_node 是 struct node 类型是否重要, 因为所有的指针都是整数,我们只是用它来存储一个 内存地址。指针类型在哪里变得相关,即为什么 我是否必须声明指针的数据类型以匹配 指针的数据类型?

指针不是整数,它们可能大于整数并且没有符号。首先,您保证该地址将适合指针。如果您不想定义结构指针,则可以使用 void 指针,但是您不能通过相同的指针轻松使用它(没有强制转换)。

我可以将所有指针声明为整数,然后显式声明 在使用之前对它们进行类型转换,以匹配指针的数据类型?

不,你不能。为此目的使用 void 指针。

【讨论】:

  • 实际上可以将指针转换(强制转换)为任何大到足以容纳它的整数类型,然后再返回。但是你不应该这样做(除了一些特殊情况)。
【解决方案4】:
When I assign the value of new_node to *head in *head = new_node, and then  
return, does the pointer new_node get destroyed, as it's an automatic variable?  

不,它没有。只要你释放它,new_node 就会有效。由于函数调用完成后您没有任何句柄,因此它的内存被泄漏。你无法找回它。

Should the memory pointer by new_node, assigned to it by the malloc  
call still be legal to access after new_node is destroyed, as it's on the heap,  
and was never de-allocated?  

与第一个答案相同

We're just using the new_node as a placeholder to store an address to some  
memory, and after we're done with the assignments and stuff, we let it go.  
Then should it matter that new_node is of type struct node, for all pointers  
are just integers, and we're just using it to store a memory address.  
Where does the pointer type become relevant i.e. why do I have to declare the  
data type of the pointer to match the pointee's datatype?  

指针应该与它指向的数据类型相同。它可能需要知道它指向的数据的大小来管理空闲等内存。

Can I just declare all pointers as integers and then explicitly typecast them  
before using, to match the pointee's datatype?  

您可以使用 void 指针跨函数传输指针。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-21
    • 2020-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多