[英]Printing Dangling Pointers in C
#include <stdio.h>
int main()
{
int *ptr;
{
int x = 2;
ptr = &x;
}
printf("%x %d", ptr, *ptr);
return 0;
}
輸出:x 的地址,x 的值。
這里, ptr
應該是一個懸空指針,對吧? 然而,它仍然存儲x
的地址。 即使在刪除該塊之后,它如何仍然指向x
的值?
#include <stdio.h>
int * func (int n)
{
int temp;
int *ptr = &temp;
temp = n * n;
return ptr;
}
int main()
{
int n = 4;
int *p = func(4);
printf("%x, %d", p, *p);
return 0;
}
輸出:臨時地址,16
在這個程序中,數據變量temp
和它的指針變量ptr
是在單獨的函數中創建的。 為什么它會產生正確的結果?
#include <stdio.h>
int * func (int n)
{
int temp;
int *ptr = &temp;
temp = n * n;
for (int i = 0; i < 10; i++)
printf("%d ", *ptr);
return ptr;
}
int main()
{
int n = 4;
int *p = func(4);
printf("\n%x, %d", p, *p);
for (int i = 0; i < 10; i++)
printf("%d ", *ptr);
*p = 12;
printf("%d\n", *p);
printf("%d\n", *p);
return 0;
}
輸出:16 16 16 16 16 16 16 16 16 16
臨時地址,1
16 16 16 16 16 16 16 16 16 16
12
12
除了 for 循環之外,上面的程序類似於第二個程序。 在main()
函數中,它每次都給出正確的輸出。 即使我嘗試將其更改為*p = 10
,無論打印多少次,它仍然會提供正確的輸出。
但是在第二個程序中,由於未定義的行為,它只給出一次正確的輸出。 它在第一個 printf 之后給出垃圾值。
但是在第三個程序中,它如何仍然每次都給出正確的輸出?
我的問題是:
謝謝大家的回答。 我現在從你所有的答案中理解。 非常感謝你。
您的兩個程序行為都未定義。
在第一個代碼中,您的程序正在通過其地址訪問x
,該地址位於聲明它的塊之外。 x
是一個局部(自動)非靜態變量,它的生命周期僅限於它的作用域1),即它被聲明的塊。 任何在其生命周期之外訪問它的嘗試都將導致未定義的行為2) 。 第二個代碼中的temp
變量也是如此。
未定義的行為包括它可能會錯誤地執行(崩潰或靜默地生成錯誤的結果),或者它可能恰好按照程序員的意圖去做。
此外,用於打印指針的正確格式說明符是%p
。
1)。 來自 C11 標准#6.2.1p4 [強調我的]
每個其他標識符的范圍由其聲明的位置決定(在聲明符或類型說明符中)。 如果聲明標識符的聲明符或類型說明符出現在任何塊或參數列表之外,則標識符具有文件范圍,該范圍在翻譯單元的末尾終止。 如果聲明標識符的聲明符或類型說明符出現在塊內或函數定義中的參數聲明列表內,則標識符具有塊作用域,在相關塊的末尾終止。 ......
2)。 來自 C11 標准#6.2.4p2 [強調我的]
2 對象的生命周期是程序執行期間保證為其保留存儲空間的部分。 一個對象存在,有一個常量地址,33) 並在其整個生命周期中保留其最后存儲的值。34)如果對象在其生命周期之外被引用,則行為是未定義的。 當指針指向(或剛剛過去)的對象到達其生命周期結束時,指針的值變得不確定。
第一個代碼中的“x”和第二個代碼中的“temp”是局部變量,因此當變量超出定義的塊時,它會從堆棧中釋放。
‘ptr’和‘p’是指向這些局部變量地址的指針,但是在局部變量從堆棧中釋放后,這些指針中存儲的值就無效了。
局部變量釋放后,值是否留在內存中,是開發工具和環境的問題。 即釋放棧,然后清空占用局部變量的指針的內存,在OS或編譯器中被處理,關鍵是你不能再使用該地址的值有效。
當我回顧 VC++2008 時,局部變量被釋放后,指針沒有更多的有效值。 它具有隨機值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.