【问题标题】:malloc memory to a pointer to pointermalloc 内存到指针的指针
【发布时间】:2012-04-29 22:26:42
【问题描述】:

我在使用指向字符的指针时遇到了这个问题:

void setmemory(char** p, int num)
{
    *p=(char*)malloc(num);
}

    void test(void)
    {
        char* str=NULL;
        setmemory(&str,100);
        strcpy(str,"hello");
        printf(str);
    }

int main()
{
    test();
    return 0;
}

上面的代码是正确的,但我不明白为什么在这里使用指向指针 char** p 的指针?为什么只使用指向 char 的指针呢?所以我把这个sn-p改成下面发现它不起作用,谁能告诉我为什么?谢谢!

void setmemory(char* p, int num)
{
    p=(char*)malloc(num);
}

void test(void)
{
    char* str=NULL;
    setmemory(str,100);
    strcpy(str,"hello");
    printf(str);
}

int main()
{
    test();
    return 0;
}

【问题讨论】:

标签: c string pointers


【解决方案1】:

这里要注意的一点是——当我们说指针时,我们通常倾向于用pass by reference 来思考,但不一定。甚至指针也可以是passed by value

char* str 是本地的 testchar* p 是本地的 setmemory 。因此,如果您不发送指向指针的指针,您在 setmemory 中所做的更改将不会在 test 中可见。

您可以使用这样的单个指针使其工作

 char * setmemory(char* p, int num) // p is a new pointer but points at the same
                                    // location as str
{
    p=(char*)malloc(num); // Now, 'p' starts pointing at a different location than 'str'
    strcpy(p ,"hello");  // Copy some data to the locn 'p' is pointing to
    return p; // Oops. The poor `str` is still pointing at NULL :( 
              // Send him the address of the newly allocated area
}

void test(void)
{
    char* str=NULL;
    str=setmemory(str,100); // We are passing a pointer which is pointing to NULL

    printf(str); //Now str points to the alloced memory and is happy :)
}

int main()
{
    test();
    return 0;
}

请注意,在setmemory 中,我们返回一个本地指针,但这不是问题(没有悬空指针问题),因为该指针指向堆上的位置而不是堆栈上的位置

【讨论】:

  • 知道了!非常感谢,pavan!很有趣很详细的解释^_^
  • @worldpeace 请记住通过勾选每个答案旁边的勾号来接受一个对您有帮助的答案
  • 对不起,另一个快速的新手问题,为什么这里不需要“免费”?我认为如果使用 malloc 总是需要 free 吗?
  • @PeteHerbertPenito 是的。完成后释放所有分配的内存是一种很好的编程习惯。但是这个例子是在处理一些其他的概念,代码只是为了说明。因此没有关注免费。
【解决方案2】:

你想改变指针,即函数需要一个引用,而不是一个值。在 C 中,这是通过将地址(指针)提供给通过更改指针本身的变量来完成的。因此,一个指针用于引用,另一个用于编程逻辑。

【讨论】:

    【解决方案3】:

    您只是在此处设置局部变量 *p。请记住,您获取的是指向数据的指针,而不是指向数据的指针。

    这样想:

    第一种情况:

    int a;
    
    foo(a); // Passes a
    void foo(int b)
    {
      b = 4;    // This only changes local variable, has no effect really
    }
    

    第二种情况:

    int a;
    foo(&a); // Passes *a
    
    void foo(int *b)
    {
      *b = 4; // This changes the contents of a. As you can see we have not changed the original pointer!
      b = 4; // This changes our local copy of the pointer, not the pointer itself, like in the first case!
    }
    

    第三种情况

    int *ptr;
    foo(&ptr); // Passes **ptr
    
    void foo(int **b)
    {
      **b = 4; // This changes the data of the passed pointer
      *b = 4; // This changes the passed pointer itself, i.e. it changes ptr. This is what test() is doing, the behavior you are looking for!
      b = 4; // This changes our local copy of a variable, just like the first case!
    }
    

    【讨论】:

      【解决方案4】:

      原始代码正在传递调用者希望放置字符串指针的位置。如果您只传入一个 'char*',调用者将按值传递调用者位置的内容 - 可能是一些未初始化的值。

      如果被调用者必须返回一个字符串或其他间接结构,则需要两个星号,以便被调用者可以返回指向调用者指针变量的指针。

      这有意义吗?它对我有用,但话又说回来,我写了它。

      【讨论】:

      • 感谢您的时间和代码!非常感谢^_^
      猜你喜欢
      • 2012-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-17
      • 2017-05-13
      • 1970-01-01
      • 2017-03-10
      相关资源
      最近更新 更多