2013-07-12 13 views
9

Rozważmy następujące instrukcje C:połączenie jednoargumentowy minus i pływaka konwersji

unsigned long x = 1; 
float a = -x; 
double b = -x; 

Oczekiwałbym jednoargumentowy minus Określenie otrzymując unsigned long wartość równą ULONG_MAX a A i B będą ustawione na pojedyncze i podwójne precyzyjne reprezentacje ULONG_MAX, odpowiednio.

Jest to wynik, który otrzymuję z gcc 4.4.7 na 32-bitowym systemie Linux oraz z kompilatorami Intel i PGI na 64-bitowym systemie Linux. W przypadku gcc (wersje testowane 4.4.7, 4.7.2 i 4.8.0, obie z -O0 i -O2) w 64-bitowym systemie Linux, podwójna zmienna b ma oczekiwaną wartość, ale zmienna a staje się równa -1 zamiast.

Natomiast następujące stwierdzenia ustawi A i B do pływających reprezentacje punktowych ULONG_MAX wszystkich kompilatorów i systemów testowałem:

unsigned long x = 1; 
unsigned long y = -x; 
float a = y; 
double b = y; 

Jeśli używam unsigned int zamiast unsigned long, otrzymuję oczekiwany wynik na wszystkich systemach.

Czy jest to niezdefiniowane zachowanie lub błąd kompilatora?

Odpowiedz

6

Jest to spowodowane błędem w GCC - konwersja typu zdarza się przed negacją.

Wydaje się, że problem występował już od jakiegoś czasu. Bug 55771 - Negation and type conversion incorrectly exchanged

W drugim przykładzie negacja ma miejsce przed konwersją typu. Jako takie widzisz oczekiwane wyniki.

+0

Dzięki za skierowanie mnie do zgłoszenia błędu! – chardmeier

+0

Dla informacji, clang 3.3 nie ma tego problemu (który jest bardzo specyficzny dla gcc). – ouah

5

To, co opisujesz, to błąd kompilatora.

(i nie ma niezdefiniowane zachowanie w poniższym programie usprawiedliwiać kompilator)

unsigned long x = 1; 
float a = -x; 
double b = -x;