Makro RAND_MAX: podpisane lub niepodpisane?
Sprawdziłem standard C (od 1999) i tylko to mówiRAND_MAX
powinien wynosić co najmniej 32767, ale nie mówi nic o tym, czy to makro powinno zostać rozszerzone na int. Specyfikacja Single UNIX (link 1, link 2) i człowiek Linuksa (połączyć) nie dodawaj żadnej jasności.
Można by pomyślećRAND_MAX
powinien byćsigned int
odkąd to jestrand()
zwraca.
Jednak odkryłem, że niektóre kompilatory definiują go jako niepodpisane:
Starożytny Turbo C ++ 1.01: #define RAND_MAX0x7FFFUNie tak stary C ++ Builder 5.5: #define RAND_MAX0x7FFFUJeszcze żywy Open Watcom C / C ++ 1.9: #define RAND_MAX32767UDJGPP (gcc 3.3.4 dla DOS): #define RAND_MAX 2147483647MinGW (gcc 4.6.2 dla Windows): #define RAND_MAX 0x7FFFMS Visual Studio 2010 (połączyć):RAND_MAX jest zdefiniowany jako wartość 0x7fffTiny C Compiler 0.9.25: #define RAND_MAX 0x7FFFlcc-win32 3.8: #define RAND_MAX 0x7fffPelles C 6.50: #define RAND_MAX 0x3fffffffLUB #define RAND_MAX 0x7fffCyfrowy Mars C / C ++ 8.52: #define RAND_MAX 32767To sprawia, że pozornie nieszkodliwy kod jak poniżej staje się nieprzenośny i wysadza w powietrze z powodu podpisania niepodpisanej promocji:
cos(w * t) + (rand() - RAND_MAX / 2) * 0.1 / (RAND_MAX / 2);
rand()
zwraca asigned int
w zakresie [0,RAND_MAX
].
JeśliRAND_MAX
jest zdefiniowany jakounsigned int
, wartość zrand()
awansuje naunsigned int
zbyt.
A jeśli tak jest, różnica(rand() - RAND_MAX / 2)
staje się niepodpisaną różnicą liczb całkowitych bez znaku z wartością w zakresach [0,RAND_MAX
-RAND_MAX
/ 2] & [UINT_MAX
+ 1-RAND_MAX
/ 2,UINT_MAX
-1] zamiast różnicy podpisanej liczb całkowitych ze znakiem z wartością w zakresie [-RAND_MAX
/ 2,RAND_MAX
-RAND_MAX
/ 2].
W każdym razie wygląda na toRAND_MAX
powinien być podpisany, a większość (?) kompilatorów definiuje go jako taki, ale czy istnieje jakieś wiarygodne źródło, które mówi, że powinno być podpisane? Starszy standard? K&R? Inna specyfikacja UNIX?