2014-09-20 35 views
-5
#include <stdio.h> 
    int main() 
    { 
     int i = 10; 
     int *p = &i; 
     foo(&p); 
     printf("%d ", *p); 
     printf("%d ", *p); 
    } 
    void foo(int **const p) 
    { 
     int j = 11; 
     *p = &j; 
     printf("%d ", **p); 
    } 

什麼是最終輸出 爲什麼第三個printf會打印未定義的值?爲什麼第三個printf會打印未定義的值?

+1

所有這三個printf都在打印11.您的預期輸出是什麼? – 2014-09-20 10:06:19

+0

C爲哪個標準? C99或更早的東西? – 2014-09-20 10:08:12

+0

未定義的值是什麼?它們全部打印11 – 2014-09-20 10:08:22

回答

0

第三個printf正在打印正確的值。問題是j是一個自動局部變量,並且一旦函數返回就不再存在。因此,main中的p未指向您期待的地方,最終程序調用了未定義的行爲

可能的解決方案:
1.使用static關鍵字的j

void foo(int **const p) 
{ 
    static int j = 11; 
    *p = &j; 
    printf("%d ", **p); 
} 

2.報關動態分配給j

void foo(int **const p) 
{ 
    int *j = malloc(sizeof(int)); 
    *j = 11; 
    *p = j; 
    printf("%d ", **p); 
} 
2

foo,你把值賦給*p指向堆棧中已分配到foo的位置。當foo返回時,堆棧彈出,並且該位置可用於重複使用  —但main中的p仍指向它。

當你調用printfmain第一次,它發生了堆棧上的該位置還沒有(還)有任何新的數據寫入到它,所以讀*p給你11,和你推上該堆棧以及一些其他用於撥打printf的東西,並且成功地打印11。但是調用printf的操作會更改堆棧上的數據,包括(可能)p(位於main)指向的位置,因爲在返回foo之後堆棧被彈出。

調用然後再次使用來自堆棧位置的數據,該數據可能已被第一次調用printf更改。

故事的道德:不要保留指向已經彈出的堆棧位置的指針。

0

foo中的「i」是堆棧分配的,每個東西都會正常工作,直到它從內存中消失,所以foo的printf將正常工作,而第二個printf和第三個printf將工作,直到整數i foo從記憶中消失。這是一個系統問題,它有可能是最後2個printf的工作或不工作。用mallo如果你想他們的工作,你需要所有的時間堆中分配的foo我整數

0

無效美孚()被調用時,新的堆棧幀是在棧上創建的,因此INT J = 11;作爲本地變量的進入此堆棧幀。所以說int j在地址0x000ffd的值爲10,所以你的* p現在存儲這個地址。現在當這個函數返回時會發生什麼堆棧展開

堆棧展開期間,它執行所有清理工作。因此所有進入該堆棧幀的數據都被破壞,因此地址0x000ffd可能具有相同的值或不同的值但變量j現在不與其關聯。所以它的未定義的行爲

相關問題