2012-05-22 54 views
13

我查了C標準(從1999年),它只是說RAND_MAX應該至少32767,但沒有說這個宏是否應擴展到一個有符號或無符號的int。單一UNIX規範(link 1,link 2)和Linux man(link)沒有增加任何清晰度。RAND_MAX宏:有符號還是無符號?

有人會認爲RAND_MAX應該是signed int因爲這就是rand()返回。

然而,我發現,有些編譯器把它定義爲無符號:

  • 古老的Turbo C++ 1.01:#定義RAND_MAX 0x7FFFU
  • 沒有這麼古老的C++ Builder的5.5:#定義RAND_MAX 0x7FFFU
  • 的還活着打開WATCOM C/C++ 1.9:#定義RAND_MAX 32767U
  • DJGPP(用於DOS的gcc 3.3.4):#定義RAND_MAX 2147483647
  • MinGW的(適用於Windows的gcc 4.6.2):#定義RAND_MAX 0x7FFF的
  • MS的Visual Studio 2010(link): RAND_MAX被定義爲值0x7FFF的
  • 微小C編譯器0.9.25:#限定RAND_MAX 0x7FFF的
  • LCC-win32的3.8:#定義RAND_MAX 0x7FFF的
  • Pellesç6.50:#定義RAND_MAX 0x3fffffff OR的#define RAND_MAX 0x7FFF的
  • 數字火星C/C++ 8.52:#定義RAND_MAX 32767

這使得表面上無害代碼像下面成爲非便攜式和炸燬由於符號到無符號推廣:

cos(w * t) + (rand() - RAND_MAX/2) * 0.1/(RAND_MAX/2); 

rand()返回的範圍內的signed int [0,RAND_MAX]。

如果RAND_MAX被定義爲unsigned intrand()的值也被提升爲unsigned int

而如果是這樣的話,所不同的(rand() - RAND_MAX/2)成爲無符號整數的與所述範圍內的值的無符號差[0,RAND_MAX - RAND_MAX/2] & [UINT_MAX + 1- RAND_MAX/2,UINT_MAX -1]代替是[ - RAND_MAX/2,RAND_MAX - RAND_MAX/2]中有符號整數的有符號差異。

無論如何,好像RAND_MAX應該簽名,並且大多數(?)編譯器將其定義爲這樣,但是是否有任何權威性來源表示應該對其進行簽名?較舊的標準? K & R?另一個UNIX規範?

+0

Plaguer&Brodie(1989)關於ANSI/ISO標準的書_Standard C_說RAND_MAX是整型常量表達式≥32767。 K&R的_The C Programming Language_(2nd-Ed 1988)只提到它與'int rand()'函數有關,後者返回一個範圍爲'0'到'RAND_MAX'的值。聲音與我簽署。 – martineau

+0

@martineau聽起來沒有指定給我。 'integer'不僅僅意味着'int','unsigned'和'int'一樣是'integer'。 –

+0

一個不合格的'int'相當於一個'signed'或'signed int',因此將相同的規則與語言規範中單詞「integer」的所有用法聯繫起來是合理的。除此之外,事實是'RAND_MAX'的唯一目的是用來描述'int rand()'函數返回值的限制,這隻會進一步加強這個假設。即爲什麼'#define'是一個'unsigned'數量,它只被用來指定返回'signed'數量的庫函數的可能返回值的範圍? – martineau

回答

3

答案是:該代碼做出了毫無根據的假設,因此需要修正。使用時,該代碼應該完成的操作是RAND_MAX(int)

雖然編譯器將其RAND_MAX宏定義爲有符號更有意義,但標準小心避免要求它們這樣做。這使得它成爲任何代碼盲目承擔簽名的可移植性錯誤。

+0

由於到目前爲止沒有人發現對「簽名或未簽名?」這個主要問題的權威答案。並且已經有足夠的時間了,這個標準看起來像是一個缺陷,我認爲現在可以關閉這個問題。因爲其他答案表達了額外的假設,我認爲這是不合理的,所以我選擇了你的答案。 –

+0

我不同意這是一個「毫無根據的假設」。在這個問題下看到我的評論。 – martineau

7

是的,這看起來像標準中的缺陷。

首先,現在可能沒有人會定義rand()返回int。其目的顯然是要返回一個正數,並且沒有可能使用負回報的錯誤回報。如果今天推出這樣的功能,將設計爲無符號整數類型作爲返回類型。我的猜測是它早於C89以及將無符號整數的概念引入語言。

然後,顯然必須期望函數返回的最大值的定義與該函數的類型相同。在其他地方,宏定義爲擴展到具有某種類型的表達式,所以這在這裏也是可能的。

至於您的問題,我認爲最簡單的方法是將的值首先縮放到[0, 1)的雙倍值,然後從中導出所有的計算結果。無論如何,如果你的平臺沒有更好的僞隨機發生器可用,你應該只使用rand()作爲最後的手段。例如在POSIX系統上,rand48系列是一種方便的替代品,具有良好的性能。

+1

如果今天設計的話,我認爲它不會返回'unsigned'。這樣做只會導致不必要的和通常有害的升級到'無符號',正如OP描述的那樣。 –

+3

@R ..反對意見的意見:我認爲會,並且'RAND_MAX'將是無符號返回類型的最大值。沒有理由浪費一點這裏的符號,也不要隨意的「數字」很容易組成更寬的隨機位向量。 –