2012-04-18 109 views
1

我也碰到这个问题,使用指针时,指针为char传来:的malloc内存的指针的指针

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的指针呢?所以我把这段代码改成了下面,发现它不起作用,谁能告诉我为什么?谢谢!

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; 
} 
+5

http://c-faq.com/ptrs/passptrinit.html – cnicutar 2012-04-18 13:39:48

+0

'p'是一个局部变量。 '* p'不是。 – 2012-04-18 13:44:08

+0

@ cnicutar,这里很好的例子,谢谢! – 2012-04-18 14:23:43

回答

3

这里要注意的一件事是 - 当我们说指针时,我们通常倾向于根据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我们正在返回本地指针一个指针工作,但它并不像该指针指向一个问题(没有悬摆指针的问题)堆上的位置而不是堆栈

+0

知道了!非常感谢,pavan!这是一个非常有趣和详细的解释^ _^ – 2012-04-18 14:17:10

+0

@worldpeace请记住接受** one **帮助您的答案,方法是勾选旁边的刻度线回答 – 2012-04-18 14:20:53

+0

对不起,另一个快速新问题,为什么在这里“免费”没有必要?如果使用malloc,我认为总是需要free? – 2012-05-18 17:55:27

0

你想改变指针,即函数需要一个引用,而不是一个值。在C中,这是通过给变量指定地址(指针)来完成的。因此,一个指针用于参考,另一个指向您的porgram逻辑。

+0

明白了,谢谢!^ _^ – 2012-04-18 14:17:29

0

您只在此设置局部变量* 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! 
} 
0

的一部开拓创新的代码被传入在哪里的位置调用者需要放置字符串指针。如果你只传入一个'char *',调用者将传值给调用者位置的内容 - 可能是一些未初始化的值。

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

这有道理吗?它对我有用,但后来我写了。

+0

感谢您在这里的时间和代码!非常感谢你^ _ ^ – 2012-04-18 14:19:27