簡體   English   中英

C中未初始化的int變量-為什么起作用?

[英]Uninitialized int variable in C - why is this working?

我已經用C編寫了一個程序,我不小心將一個未初始化的變量int放入其中。 此int編寫在函數內部,但是以某種方式在遞增后打印時,它可以正常工作。 為什么是這樣? 難道不應該是不確定的行為,實際上就是打印垃圾嗎?

int n;
int counter;

for (counter = 0; limit > counter; counter++) {
      ++n;
      printf("%d\n", n);
} 

訪問未初始化變量的值是未定義的行為。 大多數編譯器至少會對此發出警告,並且MSVC 2017默認情況下會將其視為錯誤。

您沒有辦法知道它最初包含的內容,並且如果它恰好包含了您打算立即進行的循環迭代的數量,那么將其用作循環保護而不先為其分配一個值似乎就可以運行您程序的實例。

好吧,如果保證失敗,那么它就不會是未定義的行為(a) ,它將被定義為失敗。 從字面上看,UB意味着任何事情都可能發生,包括它按預期工作的可能性。

這並不意味着可以依靠它。 您仍應避免使用UB,僅因為它可能經常以怪異的方式出現錯誤。 實際上,您的代碼完全可以打印合理的值,同時還可以靜默修改辦公桌上的隨機Excel電子表格:-)


(a)參見C11 6.7.9 Initialization /10

如果未自動初始化具有自動存儲期限的對象,則其值不確定。

C11 J.2 Undefined behaviour

具有自動存儲持續時間的對象的值在不確定時使用。

編寫本標准時,大多數形式的“不確定行為”都認識到,旨在用於不同平台和目的的實現會以不同的方式表現出來-有些有用且可預測,而另一些則沒有,並認識到“市場” [比起委員會,C更有理由判斷委員會應以何種方式表現預期的執行情況。

從歷史上看,在大多數平台上,編譯器的行為就像自動對象以某種任意方式初始化一樣,不需要花費太多,這太一致了,以至於不能用作任何類型的隨機數生成器,但對於任何類型的隨機數生成器來說,可靠性都不足以預測。其他目的, 除非在任何可能的值都與其他值一樣好的情況下 (例如,由於通常不考慮對象是否具有有用的價值而復制一個對象可能比避免不包含一個有用的值來進行復制要便宜得多]。 但是,在某些平台上,編譯器確保此類行為的唯一方法是使其明確初始化此類對象本身。 該標准的作者不想要求此類平台的編譯器使用可能會被程序員覆蓋的偽值來初始化對象,而是選擇要求其代碼必須與此類平台兼容的程序員必須確保沒有初始化就什么也沒用。

但是從那以后,事情發展到了世界上最糟糕的方向。 該標准的作者不要求強制實現應保證自動對象的行為就像在初始化時使用任意值一樣,將以零成本提供一些好處,因為他們認為沒有理由期望實現可以做任何事情否則在這種情況下。 但是,今天,某些編譯器將把一個動作作為“未定義的行為”作為事實,假設沒有程序會收到會導致該動作的輸入。 因為這樣的假設通常不是很有用,所以它們通常對程序行為沒有影響。 所有UB都會導致胡說八道的行為(您似乎在暗示)的概念是基於這樣一個事實,即使用UB推斷事情不會發生的實現,而實際上卻會發生,這很容易在代碼中生成完全荒謬的代碼。這樣的情況。 例如,積極的優化器可能會看到以下內容:

void test(int x)
{
  int y,z;
  if (x == 23)
    y=z;
  printf("%d\n",x);
}

並推斷使用x除23以外的任何值調用該函數都是“不可能的”,因此應該用puts("23");替換printf puts("23"); 我不認為任何編譯器都相當咄咄逼人 ,但它似乎流行以查看生成的代碼,將能夠輸出的其他值x為“錯過優化”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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