2012-11-19 121 views
0

可能重複:
Default values of int when not initialized in c. why do i get different outputs?Ç生成隨機值INT變量

初學者所以要律soft..am編譯下面一個簡單的代碼,我不分配給任何值我變量但C程序會生成一些隨機值,爲什麼會這樣?(只有第二個變量產生隨機整數)

那麼這些值來自哪裏?

#include<stdio.h> 

main(void) { 
    int var1; 
    int var2; 

    printf("Var1 is %d and Var2 is %d.", var1, var2); 
    return 0; //Book says I should use this for getting an output but my compiler anyways compile and return me values whether I use it or not 
} 

//Output 1st compiled: var1 = 19125, var2 = 8983 
//Output 2nd compiled: var1 = 19125, var2 = 9207 
//Output 2nd compiled: var1 = 19125, var2 = 9127 
+0

你在這裏有什麼是*不*隨機;它是根據C標準(3.19.2)定義的**不確定**。如果你想要一個僞隨機數,使用rand()。如果你想要一個*真實的*僞隨機數,是一個有福的加密庫。 – WhozCraig

回答

3

您的C程序被編譯爲某些可執行程序。請注意,如果您使用gcc -Wall在Linux上進行編譯,則會收到有關未初始化變量的警告。

var1var2變量使用一些堆棧槽或某些寄存器進行編譯。這些包含一些顯然是隨機數,你的程序打印。 (這個數字並不是真正的隨機數,它只是不可預知的垃圾)。

C語言不要求變量的隱式初始化(​​與例如Java相比)。

在實踐中,Ç我強烈建議總是明確地初始化局部變量(通常,編譯器可能是足夠聰明,甚至避免無用發射初始化)。

你所觀察到的叫做undefined behavior

你可能看到了var1不同的輸出,如果你用不同的編譯器編譯,或者用不同的優化標誌,或用不同的環境(可能再次運行您的程序可以改變輸出var1前打字export SOMEVAR=something,或用很多程序參數運行你的程序等等)。

你可以(在Linux上)編譯gcc -fverbose-asm -S和添加各種優化標誌(例如-O1-O2 ...)你的源代碼yoursource.c,並期待與一些編輯器生成的yoursource.s彙編代碼裏面。

1

var1和var2的內容未定義。因此,它們可以包含任何有效值(取決於許多外部因素)。

這是純粹的運氣,只有第二個var接縫是隨機的。嘗試在另一天,重新啓動後或啓動一些其他程序後,我敢打賭,第一個變種會改變。

+0

爲什麼'var1'值保持不變並且'var2'值發生變化? –

+0

@HelloWorld沒有任何指定'var1' _must_保持不變 - 它就這麼發生在你身上。你不應該依賴這種行爲 - 這就是行爲未定義的含義。 –

+0

@HelloWorld:不同的內存映射,不同的執行路徑 - 不同的垃圾。沒有人可以肯定地說。 – Burkhard

0

它被稱爲局部變量。任何局部變量有auto存儲符與這些在C.

位於堆棧

既然你沒有帶initilaized這些varaibles,所以它會被稱爲garbage valueindeterminate value(語言標準的任何值不強加任何要求,這必須具有特定的值),以便獲得任何隨機值。

您純粹認爲您的var1的值相同,但不是var2。 但是在任何其他系統上,它可能會給出不同的值,甚至在某個時間之後甚至可能在系統上。 所以,使用未初始化的變量是undefined behaviour

0

在C,

如果變量聲明爲全局或靜態的,那麼它們會自動初始化爲零。但是,如果它們被聲明爲本地的,那麼這些變量的值是不確定的,即,取決於編譯器。 (一些垃圾值)

2

在C語言中,當你聲明變量時,爲它們在棧上保留一些空間。堆棧是C如何跟蹤哪些參數傳遞給哪個函數,如果在函數中靜態聲明它們,存儲返回值等等,則存儲變量。每次調用一個函數時,它都會將值推入堆棧;也就是說,它會將這些值寫入堆棧中的下一個可用空間,並更新堆棧指針以對此進行解釋。當一個函數返回時,它會遞減堆棧指針,指向它在前一個函數調用中指向的位置。

如果你聲明瞭一個變量,但是你沒有初始化它,你只需要得到之前的值。如果另一個函數被調用,你可能會得到傳入該函數的參數;或者你可能會得到你要返回的函數的返回地址。

如果您提供,您顯示main()函數,沒有其他函數調用。但是,在加載程序的過程中,動態鏈接程序可能會在進程空間中調用幾個函數。所以你所看到的價值觀可能會被遺漏。

但是,您不能依賴於這些值。他們可能是任何東西;它們可以初始化爲0,它們可以是隨機數據,它們可以是任何類型的內部數據。