2011-08-19 116 views
0

我正從C++將我的一個項目轉變爲C,而且事情一直很順利,因爲我沒有使用很多C++功能開始。但是我遇到了一個奇怪的問題,我在一個小測試程序中設法複製。這對我沒有意義,所以我會嘗試用代碼解釋。函數層次結構和C指針初始化問題

typedef struct foo 
{ 
    int num1; 
    float num2; 
    char* name; 
}foo; 

//This function allocates and initializes a foo object 
foo* Initfoo() 
{ 
    foo* f = malloc(sizeof(foo)); 
    f->num1 = 1024; 
    f->num2 = 3.14; 

    f->name = malloc(100); 
    strcpy(f->name,"eleos re paidia"); 

    //Just before returning here by checking the f pointer we can see 
    // it is initialized correctly 
    return f; 
} 



void afunctest(foo* f) 
{ 
    ///... suppose this function does stuff before ... 

    //here it initializes the foo pointer 
    f = Initfoo(); 
    ///...and after here suppose the function also does more stuff.. 

    //by checking at this point in the program the pointer is still initialized 
    //correctly to what InitFoo initialized it to 
    int asd =5; 
} 


int main() 
{ 

    foo* f = 0; 

    //should do stuff and also initialize the foo* f 
    afunctest(f); 

    //when we check here the pointer f is still 0 as if afunctest() function never ran 
    int asd = 5; 

    return 0; 
} 

所以基本上用幾句話來說,我們聲明一個foo指針並將其初始化爲零。然後,我們將該指針傳遞給afunctest()函數,該函數應該執行某些操作並將其初始化以備後用。在afunctest()函數內,它似乎被正確初始化,但一旦我們回到main(),它仍然具有0的值,就好像該函數從未運行過一樣。

起初我以爲這是我原來的程序中一個非常複雜的錯誤,因爲它已經變得相當複雜,但能夠在這裏複製意味着我錯過了C語言中與C++相比使用指針的基礎知識。你可以指出嗎?我究竟做錯了什麼?提前感謝任何反饋。

P.S:我的編譯器是在Windows 7

+1

我敢打賭,你對應的C++函數具有不同的簽名,或者它也在那裏不行... – sth

回答

2

你正在改變當地的f副本GCC。這對呼叫者沒有影響。

void afunctest(foo* f) 
{ 
    f = Initfoo(); /* No effect for the caller of afunctest 
} 

嘗試是這樣的:

void afunctest(foo **f) 
{ 
    /* ... */ 
    *f = Initfoo(); 
} 

/* In main. */ 
foo* f = 0; 
functest(&f); 

順便說一下,也就是一個C FAQ: Pass pointer Init

+0

哦,所以C總是傳遞價值。這很好。然後有很多代碼來檢查類似的錯誤。謝謝你現在有道理。 – Lefteris

+0

謝謝。正如您所說,常見問題解答也可以解釋它。感覺真的很愚蠢,我不知道這一點。 – Lefteris

+0

@Lefteris:請注意,這與C++中的相同。如果您明確指定參數是引用(帶有&&),則C++僅通過引用傳遞。通常C++引用更像是指針而不是原始值,所以'foo *&f'參數通常會轉換爲'foo ** f'而不是'foo * f'。 – sth

1

C通過的值。如果您想要從afunctest()內更改f,您需要將指針傳遞給它並操縱它指向的值。

例如:

#include <stdio.h> 

static void fn (int x, int *y) { 
    x = 42;  // Changes local copy of x, doesn't affect a. 
    *y = 42; // Changes value *pointed to* by local y (which is b in caller). 
} 

int main (void) { 
    int a = 1; 
    int b = 1; 
    fn (a, &b); // Pass a and *address of* b. 

    printf ("%d %d\n", a, b); 
    return 0; 
} 

結果輸出:

1 42 

在你的代碼而言,這將是:

void afunctest (foo **f) { 
    *f = Initfoo(); 
} 

int main (void) { 
    foo* f = 0; 
    afunctest (&f); 
    return 0; 
} 
+0

哦,所以C總是傳遞價值。這很好。然後有很多代碼來檢查類似的錯誤。謝謝你現在有道理。 – Lefteris

1

該解決方案實際上是安靜直截了當 - 記住C總是按值傳遞,所以當你在func函數中設置f時,f不會更新你的f他的主要功能。

要做到這一點,你需要使用**˚F像這樣:

void afunctest(foo** f) 
{ 

    //here it initializes the foo pointer 
    *f = Initfoo(); 

} 

,並調用它像這樣:

int main() 
{ 

    foo* f = 0; 

    //should do stuff and also initialize the foo* f 
    afunctest(&f); 

    return 0; 
} 
+0

感謝您的回答。現在有道理。必須檢查我的所有代碼,然後檢查傳遞指針的函數層次結構。 – Lefteris