2017-03-16 191 views
2
#include <stdio.h> 
typedef struct { 
    int data; 
    char * string; 
}Node; 

Node * init(){ 
    Node node; 
    node.data = 5; 
    node.string = "hello"; 
    Node * point = &node; 
    return point; 
} 
int main() { 
    Node * test = init(); 
    printf("%d\n", test->data); 
    printf("%d", test->data); 
} 

爲什麼最後兩個printf語句會產生不同的結果。我懷疑是如何分配我的測試指針,但我不知道如何解決它。C語言:爲什麼這兩個printf語句輸出不同的東西

回答

3

在你的情況下,node是函數init()的局部變量,然而你返回這個地址。所以,一旦函數返回,就不再存在node

函數返回訪問後返回值正在訪問導致undefined behavior的無效內存。然而,你可以返回結構體變量本身,而不是指向它的指針,並且在調用者的另一個變量中收集返回值,它會生效。

+0

需要對代碼進行哪些更改才能解決此問題? – Madnobleman

+0

@weijazhou請重新閱讀答案中的最後一段,只是更新它。 :) –

0

節點被定義爲函數init()中的局部變量,所以它在函數返回後釋放內存。

您應該將節點定義爲全局變量(我不喜歡全局變量:-))或通過調用malloc來分配內存。

node = malloc(sizeof(Node)); 

如果您不再需要節點,請不要忘記釋放內存。

0

更新的init()返回的結構:

Node init(){ 
    Node node; 
    node.data = 5; 
    node.string = "hello"; 
    return node; 
} 

然後訪問它類似如下:

Node testNode = init(); 
printf("%d\n", testNode.data); 
printf("%d", testNode.data); 

或者,如果你想使用指針這樣的:

Node testNode = init(); 
Node* pointerToNode = &testNode; 
printf("%d\n", pointerToNode->data); 
printf("%d", pointerToNode->data); 

原因是@Sourav回答說數據將不再有效。

希望這是有用的。

1

是的,您的代碼由於返回指向函數本地對象的指針而具有未定義的行爲。但看起來你的做法是錯誤的開始。你的初始化函數應該用合適的初始值初始化一個結構體,不需要返回一個指針來完成它。你有三種選擇:

  1. 返回值,就像另一個建議的答案。

  2. 傳遞函數初始化的結構地址。這將釋放返回值,這樣你就可以通知成功或失敗:

    bool init(Node *node) { // must include stdbool.h 
        if(!node) 
         return false; 
    
        node->data = 5; 
        node->string = "hello"; 
        return true; 
    } 
    
    //... 
    
    Node test; 
    if(!init(&test)) { 
        //failed to initialize, handle the error 
    } 
    
  3. 完全放棄功能,並提供該代表的節點初始值的宏:

    #define NODE_INIT_VAL { \ 
        .data = 5, .string = "hello", \ 
    } 
    

    這可以讓你簡單地寫Node test = NODE_INIT_VAL;。這也是你希望如何初始化具有靜態存儲持續時間的任何對象。