我查看了 C 标准(从 1999 年开始),它只说RAND_MAX应该至少为 32767,但没有说明这个宏是否应该扩展为有符号或无符号 int。单一 UNIX 规范(链接 1、链接 2)和 Linux 手册(链接)并没有增加任何清晰度。
有人会认为RAND_MAX应该是 a signed int,因为这就是rand()回报。
但是,我发现一些编译器将其定义为无符号:
- 古老的 Turbo C++ 1.01:#define RAND_MAX 0x7FFFU
- 不那么古老的 C++ Builder 5.5:#define RAND_MAX 0x7FFFU
- 还活着的 Open Watcom C/C++ 1.9:#define RAND_MAX 32767U
- DJGPP(用于 DOS 的 gcc 3.3.4):#define RAND_MAX 2147483647
- MinGW(适用于 Windows 的 gcc 4.6.2):#define RAND_MAX 0x7FFF
- MS Visual Studio 2010(链接):RAND_MAX 定义为值 0x7fff
- Tiny C 编译器 0.9.25:#define RAND_MAX 0x7FFF
- lcc-win32 3.8:#define RAND_MAX 0x7fff
- Pelles 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] 范围内的 a。
如果RAND_MAX定义为unsigned int,则 from 的值也会rand()提升为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 规范?