首页 文章

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

提问于
浏览
0

我有一个名为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 回答

  • 2

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

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

    使用n1,您可以使用“address-of”运算符(&)来获取,然后发送指向变量的指针 . 该函数可以使用该指针来改变n1 .

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

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

  • 1

    当你调用 change2 时,它会覆盖 n 的值,并返回 malloc 的返回值,然后立即忘记它 . 这将不起作用,因为 main()n2 的值将保持未定义 .

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

    node * change2()
    {
       return malloc(sizeof(node));
    }
    
    ...
    
    n2 = change2();
    
  • 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
    }
    

相关问题