[英]Why is using the value of int i; undefined behaviour but using the value of rand() is not?
如果我沒有初始化i
,我不知道它的價值,但我也無法預測rand()
的值。
但另一方面,我知道未初始化的i
值在INT_MIN
和INT_MAX
之間,我也知道rand()
值介於0
和RAND_MAX
之間。
為什么使用未初始化的值, i
不確定的行為,但使用的值rand()
是不是?
未初始化變量的值未定義 。 rand()
的返回值被明確定義為給定種子的偽隨機序列中的下一個數字 。
您可以依賴 rand()
返回偽隨機數。 您不能依賴未初始化的int i
的值的任何特征。
我查閱了C99標准(ISO / IEC 9899:1999),這是我唯一可用的標准文件,但我很懷疑這些事情已經發生了變化。 在第6.2.6章類型的表示中,聲明允許整數存儲在存儲器中,填充位的值未指定,但可能包括奇偶校驗位,它將在初始化時設置,並對整數進行任何算術運算。 某些表示(例如奇偶校驗不匹配)可能是陷阱表示 ,其行為未定義 (但可能會終止您的程序)。
所以, 不,你甚至不能依賴未初始化的int i
為INT_MIN
<= i
<= INT_MAX
。
標准說從未初始化的變量讀取是未定義的行為,所以它是。 你不能說它介於INT_MIN
和INT_MAX
之間。 事實上,無法將該變量視為保留任何值,因此您甚至無法檢查該假設* 。
另一方面, rand()
旨在生成一個范圍內的隨機數。 如果從rand()
的結果中讀取未定義,則它不會是任何庫的一部分,因為它無法使用。
*通常“未定義的行為”提供優化的范圍。 優化器可以使用未初始化的變量執行任何操作,並假設它不是從中讀取的。
rand
值被定義為(偽)隨機的。 未初始化變量的值未定義為任何值。 這就是區別,無論某事被定義為有意義的東西(而rand()
也是有意義的 - 它給出(偽)隨機數)或未定義。
與其他人一樣,簡短的回答是因為標准這樣說。
訪問未初始化的變量值(在標准中描述為執行左值轉換的左值)的行為給出了未定義的行為。
rand()
被指定為給出0到RAND_MAX
之間的值,其中RAND_MAX
(在C ++的<cstdlib>
聲明的宏,C的<stdlib.h>
)被指定為具有至少32767
的值。
rand
使用算法生成您的號碼。 因此rand
不是未定義的,如果你使用srand
開始隨機生成你選擇一個像42這樣的值,你每次啟動應用程序時都會得到相同的值嘗試啟動這個例子你會看到:
#include <stdio.h>
#include <stdlib.h>
int main()
{
srand(42);
printf("%d\n", rand());
return 0;
}
另見: https : //en.wikipedia.org/wiki/List_of_random_number_generators
考慮以下代碼中的變量x
:
uint32_t blah(uint32_t q, uint32_t r)
{
uint16_t x;
if (q)
x=foo(q); // Assume return type of foo() is uint16_t
if (r)
x=bar(r); // Assume return type of bar() is uint16_t
return x;
}
由於代碼永遠不會為x
分配超出0-65535范圍的值,因此32位處理器的編譯器可以合法地為其分配32位寄存器。 實際上,由於q
的值在第一次寫入x
之后從未使用過,因此編譯器可以使用相同的寄存器來保持x
已用於保持q
。 確保函數總是返回值0-65535將需要添加一些額外的指令,而不是簡單地讓它返回分配給x
的寄存器中發生的任何事情。
請注意,從標准作者的角度來看,如果標准不要求編譯器使x
保持0-65535之間的值,那么如果代碼試圖使用,它也可能沒有指定任何可能發生的事情。 x
。 希望在這種情況下提供任何行為保證的實現可以自由地執行,但標准沒有要求。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.