我查阅了 C 标准(从 1999 年开始),它只说RAND_MAX
应该至少为 32767,但没有说明该宏是否应扩展为有符号整数或无符号整数。单一 UNIX 规范 (link 1 http://pubs.opengroup.org/onlinepubs/7908799/xsh/stdlib.h.html, link 2 http://pubs.opengroup.org/onlinepubs/7908799/xsh/rand.html)和 Linux 人(link http://www.kernel.org/doc/man-pages/online/pages/man3/rand.3.html)不要增加任何清晰度。
有人会认为RAND_MAX
应该是一个signed int
因为那就是rand()
返回。
但是,我发现一些编译器将其定义为无符号:
- 古老的 Turbo C++ 1.01:#define RAND_MAX0x7FFFU
- 不那么古老的 C++ Builder 5.5:#define RAND_MAX0x7FFFU
- 仍然存在的 Open Watcom C/C++ 1.9:#define RAND_MAX32767U
- DJGPP(gcc 3.3.4 for DOS):#define RAND_MAX 2147483647
- MinGW(gcc 4.6.2 for Windows):#define RAND_MAX 0x7FFF
- MS Visual Studio 2010(link http://msdn.microsoft.com/en-us/library/2dfe3bzd%28v=vs.100%29.aspx): RAND_MAX 定义为值 0x7fff
- Tiny C 编译器 0.9.25:#define RAND_MAX 0x7FFF
- lcc-win32 3.8:#define RAND_MAX 0x7fff
- 佩莱斯 C 6.50:#define RAND_MAX 0x3fffffff 或 #define RAND_MAX 0x7fff
- 数字火星 C/C++ 8.52:#define RAND_MAX 32767
这使得像下面这样看似无害的代码变得不可移植,并由于签名到未签名的升级而崩溃:
cos(w * t) + (rand() - RAND_MAX / 2) * 0.1 / (RAND_MAX / 2);
rand()
返回一个signed int
在范围 [0,RAND_MAX
].
If RAND_MAX
被定义为unsigned int
,值来自rand()
晋升为unsigned int
too.
如果是这样的话,区别就在于(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 规范?