Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
malloc内存指向指针指向指针_C_String_Pointers - Fatal编程技术网

malloc内存指向指针指向指针

malloc内存指向指针指向指针,c,string,pointers,C,String,Pointers,我在使用指向字符的指针时遇到了这个问题: 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()

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

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;
}
上面的代码是正确的,但我不明白为什么在这里使用指向指针字符**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语言中,这是通过给变量指定地址(指针)来实现的,而变量的地址是通过改变指针本身来实现的。因此,一个指针用于引用,另一个指针用于程序逻辑。

这里需要注意的一件事是——当我们说指针时,我们通常倾向于按引用传递
来思考,但不一定。甚至指针也可以通过值传递

char*str
是本地的
test
char*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
中,我们返回一个本地指针,但这不是问题(没有悬空指针问题),因为该指针指向堆上而不是堆栈上的某个位置

这里只设置了局部变量*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!
}

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

如果被调用方必须返回字符串或其他间接结构,则需要两个星号,以便被调用方可以将指针返回到调用方指针变量中


这有意义吗?它对我有影响,但我还是写了它。

p
是一个局部变量<代码>*p
不是。@cnicutar,这里是一个很好的例子,谢谢!明白了!非常感谢你,pavan!这是一个非常有趣和详细的解释^ ^@worldpeace记住接受其中一个答案,通过检查每个答案旁边的勾号来帮助你对不起,另一个快速的新问题,为什么这里不需要“免费”?我认为如果使用malloc,总是需要免费的吗?@PeteHerbertPenito是的。一旦完成,释放所有malloced内存是一种很好的编程实践。但是这个例子处理的是其他一些概念,代码只是为了说明。因此,没有重点免费。谢谢你的时间和代码在这里!我非常感谢^_^