[英]Casual value of a not initialized pointer to pointer
當我定義一個指針而不初始化它時:
int *pi;
它指向 memory 的隨機部分。
當我定義一個指向指針而不初始化它的指針時會發生什么?
int **ppi;
它指向哪里? 它應該指向另一個指針,但我沒有定義它,所以它可能指向 memory 的隨機部分? 如果可能的話,你能用一個例子來說明一下區別嗎?
為了清楚起見,請考慮以下聲明
T *ptr;
其中T
是某個類型說明符。 如果聲明的變量ptr
具有自動存儲持續時間,則指針不會顯式或隱式初始化。
所以指針有一個不確定的值。
T
可以是任何類型。 您可以將 T 定義為例如
typedef int T;
或者
typedef int *T;
指針是標量對象。 因此在這個聲明中
typedef int *T;
T *ptr;
指針ptr
具有與聲明中相同的不確定值
typedef int T;
T *ptr;
任何未初始化的局部變量都包含一個不確定的值。 不分類型。 例如,未初始化的int
、 int*
或int**
之間沒有明顯的區別。
然而,C 中有一條規則說,如果你不訪問這種未初始化的局部變量的地址,而是使用它的值,你就會調用未定義的行為——這意味着一個錯誤,可能是一個崩潰等。基本原理很可能是這樣的變量可以分配在寄存器中,並且沒有可尋址的 memory 位置。 有關詳細信息,請參閱https://stackoverflow.com/a/40674888/584518 。
所以下面的這些例子都是不好的和錯誤的,因為局部變量本身的地址從來沒有被使用過:
{
int i;
int* ip;
int** ipp;
printf("%d\n, i); // undefined behavior
printf("%p\n, (void*)ip); // undefined behavior
printf("%p\n, (void*)ipp); // undefined behavior
}
但是,如果您在某處獲取變量的地址,則 C 不那么嚴格。 在這種情況下,您最終會得到一個不確定的變量值,這意味着它可以包含任何內容,並且如果您多次訪問它,該值可能會不一致。 在指針的情況下,這可能是“隨機地址”,但不一定如此。
不確定的值可能是所謂的“陷阱表示”,即該類型的禁止二進制序列。 在這種情況下,訪問變量(讀取或寫入)會調用未定義的行為。 這對於普通int
不太可能發生,除非您有一個不使用 2 補碼的非常奇特的系統 - 因為在標准 2 的補碼系統中, int
的所有值組合都是有效的,並且沒有填充位、負零等。
示例(假設 2 的補碼):
{
int i;
int* ip = &i;
printf("%d\n", *ip); // unspecified behavior, might print anything
}
未指定的行為意味着編譯器不需要記錄該行為。 你可以得到任何一種 output 並且它不需要是一致的。 但至少程序不會像在未定義行為的情況下那樣崩潰和燒毀。
但是陷阱表示更可能是指針變量的事情。 一個特定的 CPU 可能有一個受限的地址空間或在低級別初始化,MMU 可以設置為具有某些虛擬區域,某些區域僅包含數據或某些區域僅包含代碼等。即使您將無效地址值讀入索引寄存器,CPU 也會產生硬件異常。 如果您嘗試通過無效地址訪問 memory,它肯定很有可能這樣做。
例如,MMU 可能會阻止試圖從 memory 的數據段執行代碼的失控代碼,或者像訪問數據一樣訪問代碼 memory 的內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.