使用指针和指针指向内存分配

时间:2014-04-02 18:15:02

标签: c pointers segmentation-fault

我有一个名为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()后无法反映更改。谢谢!

3 个答案:

答案 0 :(得分:2)

暂时忽略n1和n2是指针的事实。只需将它们视为任何其他变量即可。

C只有"按值"调用,这意味着当您调用函数时,会复制参数的值,并将这些副本发送到函数。如果使用变量作为参数调用函数,则会复制并发送其值。这意味着被调用的函数不能改变变量的内容。

使用n1,您可以使用"地址" operator(&)获取,然后发送指向变量的指针。该函数可以使用该指针来改变n1。

使用n2,您只需发送变量的值,因此函数无法更改变量。 n2将保留其旧值,这就是发生在该内存位置的垃圾。

稍后在程序中,您可以按照n1和n2中的指针进行操作。由于n2包含垃圾,因此您可以获得C标准所称的"未定义的行为",在这种情况下,您的程序崩溃了。

答案 1 :(得分:1)

当您致电change2时,它会覆盖传递的nmalloc,然后立即忘记它。这不起作用,因为n2main()的值仍未定义。

如果您不想使用指向指针的指针,则必须使用其他机制来返回值,例如

node * change2()
{
   return malloc(sizeof(node));
}

...

n2 = change2();

答案 2 :(得分:0)

在第二个函数中,npointer 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
}