2017-07-15 64 views
1

有人請向我解釋爲什麼輸出下面的代碼是6而不是5?我不明白如何調用hoo改變m-> x的值。即使在運行代碼並遵循其每一步之後,仍然不清楚。結構和指針。輸出不清楚

#include <stdio.h> 
#include <stdlib.h> 

typedef struct a { 
    int x; 
    struct a* next; 
}a_t; 

a_t* foo() { 
    a_t* varp, var = { 5,NULL }; 
    varp = &var; 
    return varp; 
} 

a_t* hoo() { 
    a_t* varp, var = { 6,NULL }; 
    varp = &var; 
    return varp; 
} 

void main() 
{ 
    a_t* m = foo(); 
    hoo(); 
    printf("%d", m->x); 
} 
+1

你的代碼是未定義的行爲。 – tilz0R

+1

'var.x'在'foo'之外無效。 – BLUEPIXY

+1

因爲你不能從一個函數返回一個局部變量。您的指針指向您嘗試訪問時已釋放的數據。 SO上有很多重複的內容。 –

回答

2

你的功能hoofoo正在返回指向局部變量是定義*不確定behavior`。

它們都執行不同的結構(2個副本),並且您從第一個打印值。

由於您首次在函數foo上創建了堆棧結構,因此您有幸在功能hoo的函數中同時創建了堆棧上的函數。

因此你有覆蓋。

如果要從函數返回指針,請使用static或使用malloc在堆上動態分配內存。

a_t* foo() { 
    a_t* varp = malloc(sizeof(*varp)); 
    varp->m = 5; 
    return varp; 
} 

void main() 
{ 
    a_t* m = foo(); 
    hoo(); 
    printf("%d", m->x); 
    free(m); 
} 

現在你在堆棧外分配內存,它將按照你的預期工作。

+0

謝謝你的明確答案。代碼錯誤的目的是它是我發現練習的一部分。我只是沒有任何解釋的輸出,並想知道在內存中發生了什麼。 – roy360

+0

返回指向本地變量的指針本身不會導致未定義的行爲。調用者解除引用這些指針的任何嘗試都會發生。 – Peter

+0

@彼得是的,我同意你的看法。 – tilz0R

2

您的代碼有未定義的行爲。讓我們看看爲什麼。

a_t* foo() { 
    // creates a variable on the stack 
    a_t* varp, var = { 5,NULL }; 
    // sets address of variable on stack to another variable on the stack 
    varp = &var; 
    // you return that address on the stack 
    return varp; 
} 

a_t* hoo() { 
    // creates a variable on the stack 
    a_t* varp, var = { 6,NULL }; 
    // sets address of variable on stack to another variable on the stack 
    varp = &var; 
    // you return that address on the stack 
    return varp; 
} 

爲什麼以上代碼爲undefined behavior?在函數調用hoofoo結束後,您將返回您不再擁有的變量(包含地址)。 系統現在擁有該內存! 電腦很愚蠢,會盲目地執行你給他們的任何命令。我想你打算使用malloc來保存你想要在函數調用堆外保存的變量。

a_t* foo() { 
    a_t *varp = malloc(sizeof(struct a_t)); 
    varp->x = 5; 
    varp->next = NULL; 
    return varp; 
} 

你能修復另一個嗎?

+0

非常感謝,非常清楚的解釋。 – roy360

2

基本上,當你調用hoo()時,你創建了一個與使用foo之前創建的var和var不同的var和var,並將它存儲在變量m中。然而,這個新的varp被創建在與var的var相同的內存地址上並且覆蓋了它的值。

如果您使用F5逐行執行並在main行中添加3個斷點,請在變量m上添加一個監視,然後進入hoo(),並注意分配給varp的內存地址與m ...因此,當你離開hoo()並返回到main時,將丟失以m爲單位存儲的值,因爲它已被覆蓋。notice the cursor is still at line 22 and didn't overwrite yet

+0

謝謝!我從中學到了很多 – roy360

0

您可以定義「static var ...」。 因此var在函數返回後仍然存在。