【问题标题】:Memory allocation using pointer and pointer to pointer使用指针和指向指针的指针分配内存
【发布时间】:2014-04-02 18:15:02
【问题描述】:

我有一个叫做节点的结构:

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() 后无法反映更改。谢谢!

【问题讨论】:

    标签: c pointers segmentation-fault


    【解决方案1】:

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

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

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

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

    稍后在程序中,您可以按照 n1 和 n2 中的指针指向它们所指向的任何内容。由于 n2 包含垃圾,您会得到 C 标准所称的“未定义行为”,在这种情况下您的程序崩溃了。

    【讨论】:

      【解决方案2】:

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

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

      node * change2()
      {
         return malloc(sizeof(node));
      }
      
      ...
      
      n2 = change2();
      

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-05-16
          • 1970-01-01
          • 2015-12-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多