2011-02-08 43 views
1

我想創建一個鏈接列表,您可以更新節點中的數據,但無論我嘗試什麼,C似乎都不允許我更新空指針的值(或者更確切地說它指向的點至)。下面是測試代碼,我有:如何修改指針以通過函數void?

void newData(void * d) 
{ 
    char data[] = "world"; 

    d = &data; 
} 

int main() 
{ 
     char testData[] = "hello"; 
     void * testPointer = &testData; 

     printf("TestData is %s\n", (char *)testPointer); 

     // Modify the data 
     newData(&testPointer); 

     printf("TestData is %s\n", (char *)testPointer); 
} 

剛剛輸出::

TestData is hello 
TestData is hello 

我缺少明顯的東西嗎?我也嘗試使用指針指針,但無濟於事。

+2

參數類型是錯誤的,應該是無效** 。 – 2011-02-08 20:29:47

+0

或者只是將它稱爲`newData(testPointer);'? – John 2011-02-08 20:32:56

+0

`void * testPointer =&testData;`此語句中不需要地址運算符。當你給一個指針分配一個數組時,數組的地址get被賦值。所以,你可以做`void * testPointer = testData;`。在你的程序中還有其他的陳述,你可以做到這一點。 – Mahesh 2011-02-08 20:40:57

回答

4

兩件事情是不對的:

char data[] = "world"; 

可能創建爲函數的棧幀的一部分。數組降級爲指針。因此,當函數調用ret時,它應該已經清理了它的堆棧,並且該地址處的內存不見了。如果這裏有任何操作,那是因爲你還沒有覆蓋內存。

你能做什麼?聲明它static是一種解決方案,它保證(至少根據c99)程序生存期(即不會在堆棧中分配,但在數據段中,並且C庫在main之前爲您分配)。然而,由於我懷疑這只是一個演示,這是值得指出的是:

char data[] = "world"; 
memcpy(d, data, 5); 

是完全有效的,因爲你複製的內容,而不是指向值。

newData(&testPointer); 

你在這裏犯了一個簡單的錯誤。彙編中的指針是一個存儲地址,用於存儲另一個內存地址。當你傳遞一個指向函數的指針時,你想傳遞這個內存地址,這樣當你調用這個函數時,指針的內容(一個內存地址)就會以一個新指針的形式被複制到堆棧上。當然,這兩個指針都指向相同的東西,這就是你最終實現了通過引用類型的東西。如果你不相信我,請在調試器中觀看。

但是,你在做什麼是傳遞一個指針的地址,所以你正在創建一個指針指向一個值的指針。想象一下,像這樣的記憶:

|Address|Value 
|0x120 |0x121 <-- this is what you're passing with &testPointer 
|0x121 |0x122 <-- this is a pointer; it contains the address of a value 
|0x122 |h  <-- this is a value. 
|0x123 |e 
|0x124 |l 
... 

我希望這是更清晰。在我簡單的記憶中,你傳遞的是0x120而不是0x121。你當然可以解除引用兩次,但爲什麼?簡單的解決辦法就是通過指針這樣的:

newData(testPointer); 
7

我想你需要

void newData(void ** d) 
{ 
    char data[] = "world"; 
    *d = &data; 
}  

然而,這有它自己的問題,因爲「世界」是堆棧地方,並從newData返回後,將不再有效。

0

我想有點變化的代碼就可以解決問題:

void newData(void ** d) 
{ 
    char* data = "world"; 

    *d = data; 
}