2011-04-16 26 views
3

我發現了一些代碼,我對這個循環如何退出以及它如何工作感到困惑。程序是否產生確定性輸出?這個循環如何結束並且結果是確定性的?

我百思不得其解的原因是:

1. `someArray` is of size 2, but clearly, the loop goes till size 3, 
2. The value is deterministic and it always exits `someNumber` reaches 4 

能有人請解釋這是怎麼回事?

當我將尖括號<>放在include的庫名稱周圍時,代碼打印不正確。

#include <stdlib.h> 
#include <time.h> 
#include <stdio.h> 

int main() { 
    int someNumber = 97; 
    int someArray[2] = {0,1}; 
    int findTheValue; 

    for (findTheValue=0; (someNumber -= someArray[findTheValue]) >0; findTheValue++) { 

    } 
     printf("The crazy value is %d", findTheValue); 
    return EXIT_SUCCESS; 
} 
+0

真的,我會猜測findTheValue會= 0作爲輸出...因爲,someNumber - = someArray [findTheValue]當findTheValue == 0肯定是> 0 ... – Dair 2011-04-16 06:27:11

+0

@anon:循環繼續,直到條件是錯誤的 – Brad 2011-04-16 06:40:33

+0

它可能在您的計算機上每次都有效,但不是確定性的。僅僅因爲它在你運行時工作並不意味着代碼是好的。 – 2011-04-16 09:02:56

回答

1

根據您的編譯器,someArray[2]是指向findTheValue

因爲這些變量是一個接一個地聲明的,所以它們完全有可能在內存中連續定位(我相信在堆棧中)。 C沒有真正執行任何內存管理或錯誤檢查,因此someArray[2]僅表示內存在someArray[0] + 2 * sizeof(int)

所以當findTheValue是0時,我們減去,那麼當findTheValue爲1時,我們減去1,當findTheValue是2時,我們減去someNumber(現在是94)並退出。

此舉並不保證。不要依賴它!

編輯:它可能更可能是someArray [2]只是指向你的RAM中的垃圾(未指定)值。這些值可能超過93,並會導致循環退出。

編輯2:或者也許someArray[2]someArray[3]是大負數,並且減去這兩個值都會導致someNumber翻轉爲負數。

+0

我已經在計算機上多次運行此程序,並且始終獲得相同的輸出...您確定嗎?這是他的完全相同的輸出以及... – Dair 2011-04-16 06:34:53

+0

你可能是對的。我編輯了我的帖子。嘗試在循環內打印someArray [findTheValue]的值並告訴我們你看到了什麼? – Brad 2011-04-16 06:41:17

+0

@mu:是的,堆棧。固定:) – Brad 2011-04-16 06:42:10

1

循環退出,因爲(someNumber - = someArray [findTheValue])沒有設置。

添加調試行,你可以看到

value 0 number 97 array 0 
value 1 number 96 array 1 
value 2 number 1208148276 array -1208148180 

正在打印出來findTheValue,someNumber,的someArray [findTheValue]

它不是答案,我會第一眼預料。

+0

對不起,但我根本沒有得到你顯示的輸出。我正在使用ubuntu 64位,海灣合作委員會版本4.4.5 – Jimm 2011-04-16 07:00:11

+0

我回應了布拉德的迴應與我的輸出。正如你所看到的,someNumber - = someArray [findTheValue]的值總是被設置的,我可以在for循環結束後打印這個值。 – Jimm 2011-04-16 07:04:23

+1

正如其他人指出的那樣,問題是位於數組[2]中的值實際上是隨機的,因此您可以並且將得到不同的結果。 – BugFinder 2011-04-16 07:06:22

0

檢查地址:

printf("&someNumber = %p\n", &someNumber); 
printf("&someArray[0] = %p\n", &someArray[0]); 
printf("&someArray[1] = %p\n", &someArray[1]); 
printf("&findTheValue = %p\n", &findTheValue); 

給這個輸出:

&someNumber = 0xbfc78e5c 
&someArray[0] = 0xbfc78e50 
&someArray[1] = 0xbfc78e54 
&findTheValue = 0xbfc78e58 

看來,由於某些原因,編譯器把數組中的堆棧區的開始,那麼該聲明的變量然後按照他們聲明的順序在上面。所以someArray [3]有效地指向someNumber。

我真的不知道原因,但我嘗試了Ubuntu 32位和Visual Studio上的gcc,並且沒有進行優化,結果總是相似。

2

訪問超出其界限的數組元素是未定義的行爲。也就是說,該程序被允許做任何事情,回覆42,吃掉你的硬盤或花你所有的錢。換句話說,在這種情況下發生的事情完全取決於平臺。它可能看起來是「確定性的」,但這僅僅是因爲你很幸運,也可能是因爲你只是從那個地方閱讀而沒有寫信給它。

這種代碼很糟糕。不要這樣做。