我有一个名为node的结构:
typedef struct node
{
int x;
struct node *next;
}node;
我有两个函数 change1()和 change2(),它们为节点分配内存。 change1()将指针指向, change2()将指针指向作为参数。
void change1(node ** n)
{
*n = malloc(sizeof(node));
}
void change2(node * n)
{
n = malloc(sizeof(node));
}
如果我拨打更改2(& n )&然后尝试将值分配给x(在从函数调用返回到change2 之后的main中的)并打印它,我得到4作为输出但是如果我调用 change1( n )&做同样的事情我得到了细分错误。
void main()
{
node * n1,*n2 ;
change1(&n1); // Pretty much OK
change2(n2); // Leads to segmentation fault on printing
n1->x = 4;
n2->x = 4;
printf("%d ",n1->x);
printf("%d ",n2->x); // gives SEGMENTATION fault
}
有人可以解释在内存分配方面发生了什么,以及为什么我作为n2发送的指针在返回main()后无法反映更改。谢谢!
答案 0 :(得分:2)
暂时忽略n1和n2是指针的事实。只需将它们视为任何其他变量即可。
C只有"按值"调用,这意味着当您调用函数时,会复制参数的值,并将这些副本发送到函数。如果使用变量作为参数调用函数,则会复制并发送其值。这意味着被调用的函数不能改变变量的内容。
使用n1,您可以使用"地址" operator(&)获取,然后发送指向变量的指针。该函数可以使用该指针来改变n1。
使用n2,您只需发送变量的值,因此函数无法更改变量。 n2将保留其旧值,这就是发生在该内存位置的垃圾。
稍后在程序中,您可以按照n1和n2中的指针进行操作。由于n2包含垃圾,因此您可以获得C标准所称的"未定义的行为",在这种情况下,您的程序崩溃了。
答案 1 :(得分:1)
当您致电change2
时,它会覆盖传递的n
值malloc
,然后立即忘记它。这不起作用,因为n2
中main()
的值仍未定义。
如果您不想使用指向指针的指针,则必须使用其他机制来返回值,例如
node * change2()
{
return malloc(sizeof(node));
}
...
n2 = change2();
答案 2 :(得分:0)
在第二个函数中,n
是pointer to a node
。因此,第二个函数只能修改节点的成员,例如
void change2( node *n )
{
n->x = 4;
n->next = NULL;
}
但是,这假定main
已提供存储节点的内存。因此main
必须执行以下操作之一
int main( void )
{
node n2; // allocate n2 on the stack
change2( &n2 ); // pass the address of the node to the change2 function
printf( "%d\n", n2.x ); // use 'dot' notation to access members of struct
}
---或---
int main( void )
{
node *n2; // n2 is a pointer on the stack
n2 = malloc(sizeof(node)); // allocate memory to store the node data
change2( n2 ); // pass the pointer, i.e. pass the address of the node to the change2 function
printf( "%d\n", n2->x ); // use pointer notation, since n2 was declared as a pointer
}
abligh
提到的第三种方法是在函数中分配内存并将指针返回给main。
node *create2( void )
{
node *n2; // declare the pointer
n2 = malloc(sizeof(node)); // allocate memory to store the node data
n2->x = 4; // initialize the members of the node
n2->next = NULL;
return( n2 ); // return a pointer to the node
}
int main( void )
{
node *n2; // n2 is just a pointer
n2 = create2(); // allocate memory for and initialize a node
printf( "%d\n", n2->x ); // use pointer notation, since n2 is as a pointer
}