这个结构指针会发生什么?

时间:2014-06-17 08:25:09

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

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

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的值分配给*head = new_node,然后返回时,指针new_node是否会被销毁,因为它是一个自动变量?

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

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

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

4 个答案:

答案 0 :(得分:2)

  1. 不,您使用new_node作为指向结构类型的指针,该结构类型包含字段data和另一个字段nextvoid *(或更糟糕的是,整数)不会让你这样做。编译器需要类型信息来理解像new_node->data = data;这样的表达式。
  2. 当然(对于某些合适的整数类型),但为什么?!

答案 1 :(得分:2)

  

当我在* head = new_node中将new_node的值赋给* head时,和   然后返回,指针new_node是否被破坏,因为它是一个   自动变量?

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

  

内存指针应该由new_node指定,由malloc分配给它   在new_node被销毁之后调用仍然是合法的,因为它已经打开了   堆,并且从未被解除分配?

这是合法的,你可以使用它。

  

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

指针不是整数,它们可能大于整数而且它们没有签名。首先,您保证地址适合指针。如果你不想定义一个结构指针,你就可以使用一个空指针,但是你不能轻易地使用它(没有一个强制转换)和相同的指针。

  

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

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

答案 2 :(得分:2)

  

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

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

  

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

类型安全。当你指向一个字符的指针时,它将是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

答案 3 :(得分:1)

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指针在函数之间传输指针。