簡體   English   中英

未初始化的指向指針的指針的臨時值

[英]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;

任何未初始化的局部變量都包含一個不確定的值。 不分類型。 例如,未初始化的intint*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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM