我有一个名为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));
}
如果我调用 change2(&n) 然后尝试为x分配一个值(在从函数调用返回到change2之后的main中)并打印它,我得到4作为输出但如果我调用 change1(n) 并做同样的我得到 segmentation 错误 .
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()后无法反映更改 . 谢谢!
3 回答
暂时忽略n1和n2是指针的事实 . 只需将它们视为任何其他变量即可 .
C只有“按值调用”,这意味着当您调用函数时,将复制参数的值,并将这些副本发送到函数 . 如果使用变量作为参数调用函数,则会复制并发送其值 . 这意味着被调用的函数不能改变变量的内容 .
使用n1,您可以使用“address-of”运算符(&)来获取,然后发送指向变量的指针 . 该函数可以使用该指针来改变n1 .
使用n2,您只需发送变量的值,因此该函数无法更改变量 . n2将保留其旧值,这就是在该内存位置发生的任何垃圾 .
稍后在程序中,您可以按照n1和n2中的指针进行操作 . 由于n2包含垃圾,因此您可以获得C标准所称的“未定义行为”,在这种情况下,您的程序崩溃了 .
当你调用
change2
时,它会覆盖n
的值,并返回malloc
的返回值,然后立即忘记它 . 这将不起作用,因为main()
中n2
的值将保持未定义 .如果您不想使用指向指针的指针,则必须使用其他一些机制来返回值,例如
在第二个函数中,
n
是pointer to a node
. 因此,第二个功能只能修改节点的成员,例如,但是,这假设
main
已提供存储节点的内存 . 因此main
必须执行以下操作之一如
abligh
所述,第三种方法是在函数中分配内存并将指针返回给main .