2013-07-12 9 views
9

Рассмотрим следующие операторы C:сочетание унарный минус и поплавком преобразования

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

Я хотел бы ожидать унарным термин минус, чтобы получить беззнаковое длинное значение, равное ULONG_MAX и а и б, чтобы быть установлен в одинарной и двойной прецизионные представления ULONG_MAX, соответственно.

Это результат, который я получаю с gcc 4.4.7 на 32-разрядной Linux и с компиляторами Intel и PGI в 64-разрядной Linux. Однако с gcc (проверенные версии 4.4.7, 4.7.2 и 4.8.0, как с -O0, так и -O2) в 64-разрядной Linux, двойная переменная b имеет ожидаемое значение, но float a становится равным -1 вместо.

В противоположность этому, следующие операторы будут устанавливать как а и Ь с плавающей точкой представления ULONG_MAX на всех компиляторов и систем я тестировал:

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

Если я использую неподписанных Int вместо неподписанных долго, я получаю ожидаемый результат на всех системах.

Это какое-то неопределенное поведение или ошибка компилятора?

ответ

6

Это связано с ошибкой в ​​GCC - преобразование типа происходит до отрицания.

Вопрос, кажется, был вокруг какое-то время. Bug 55771 - Negation and type conversion incorrectly exchanged

Во втором примере отрицание происходит до преобразования типа. Таким образом, вы видите ожидаемые результаты.

+0

Спасибо, что указали мне на отчет об ошибке! – chardmeier

+0

Для информации, clang 3.3 не имеет этой проблемы (которая очень специфична для gcc). – ouah

5

Что вы описали, это ошибка компилятора.

(и не определено поведение в программе ниже извинить компилятор)

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