2012-09-16 103 views
2

下面的C代碼片段:空指針作爲參數

[...] 
void f1(void* a){ 
    printf("f(a) address = %p \n",a); 
    a = (void*)(int*)malloc(sizeof(int)); 

    printf("a address = %p \n",a); 
    *(int*)a = 3; 

    printf("data = %d\n",*(int*)a); 
} 

void f(void){ 
    void* a1=NULL; 
    printf("a1 address = %p \n",a1); 

    f1(a1); 

    printf("a1 address = %p \n",a1); 
    printf("Data.a1 = %d\n",*(int*)a1); 
} 
[...] 

結果

a1 address = (nil) 
f(a) address = (nil) 
a address = 0xb3f010 
data = 3 
a1 address = (nil) 
Segmentation fault (core dumped) 

爲什麼不a1保持已分配給它的函數地址?

+4

查找「按價值傳遞」。 – Mysticial

+0

因爲你通過它傳遞價值。 –

+2

http://c-faq.com/ptrs/passptrinit.html –

回答

4

由於這是C,您不能通過引用傳遞指針而不傳遞指向指針的指針(例如,void **而不是指向指針的void *)。你需要返回新的指針。這是怎麼回事:

f(a1); 

推動指針(NULL)爲a棧參數值的價值。 a選取此值,然後重新分配一個新值(malloc ed地址)。當它通過價值傳遞時,a1沒有任何變化。

如果這是C++,你可以達到你做通過引用傳遞指針想要的東西:

void f(void *&a); 
+3

在C中,你可以用'void f(void ** a)'來做到這一點。 – chris

+0

@chris好點。大腦放屁時刻。 – pickypg

4

指針傳遞到a1你的功能,你不能變化,其中a1點。指針是傳遞值,所以在f1你只更改a持有的地址的副本。如果你想改變指針,即對傳入的指針分配新的內存,那麼你就需要一個指針傳遞給一個指針

void f1(void **a) 
{ 
    // ... 
    *a = malloc(sizeof(int)); 
    // ... 
3

要通過函數調用改變一個變量時,函數需要具有參考語義相對於參數。 C沒有本地引用變量,但可以通過獲取地址和傳遞指針來實現引用語義。

一般:

void mutate_thing(Thing * x) // callee accepts pointer 
{ 
    *x = stuff;     // callee derefences ("*") 
} 

int main() 
{ 
    Thing y; 
    mutate_thing(&y);   // caller takes address-of ("&") 
} 

在你的情況下,Thingvoid *

void f(void ** pv) 
{ 
    *pv = malloc(12); // or whatever 
} 

int main() 
{ 
    void * a1; 
    f(&a1); 
} 
0

基於Kerrek SB的例子中,我用這個來證明無效指針到指針參數和它如何使用。

#include <stdio.h> 

void test(void ** jeez) 
{ 
    *jeez = (void *) (int) 3; 
} 


int main (int argc, char* argv[]) 
{ 
void *a; 
test(&a); 

int b = *(int *)&a; 
printf("value returned = %d\n", b); 

return 0; 
}