Can unsigned long become negative when multiplied by float?

The title is probably poorly matched, but I could not find a good one-line resume for this question. My problem is that I cannot understand what my compiler is doing, and I am wondering if I found an error in the compiler ... or in my understanding of C.

I understand that:

  • - 1UL == ULONG_MAX , and this is safe, since the behavior of overflowing unsigned numbers is well defined
  • product (- 1UL) * 1.0f enables the conversion of the left operand to float, and this conversion retains the value (namely ULONG_MAX ), with the exception of rounding errors

So far, my compiler agrees if 1UL not a variable. Here is my test program with its output in the form of comments:

 #include <stdio.h> int main(void) { unsigned long one = 1; unsigned long minus_one = - one; printf("%lu\n", - one); // 18446744073709551615 printf("%g\n", minus_one * 1.0f); // 1.84467e+19 printf("%g\n", (- one) * 1.0); // 1.84467e+19 printf("%g\n", (- 1UL) * 1.0f); // 1.84467e+19 printf("%g\n", (- one) * 1.0f); // -1 return 0; } 

I can not understand the last conclusion. I tried different optimization levels and different language standards (C90, C99 and C11) with the same results. Someone tell me?

Environment: gcc 4.8.1 / Ubuntu Linux 14.04 / x86-64 (I32LP64)

Change I just noticed that my question may be a duplicate of a combination of unary minuses and conversion on boards .

+6
source share
1 answer

This seems to be a bug in gcc 4.8. I have the same behavior as you have with 4.8, but gcc 4.9 and clang show the corrected behavior.

+3
source

Source: https://habr.com/ru/post/982373/


All Articles