The title is probably ill-chosen, but I could not find a good one-line summary for this question. My problem is that I cannot make sense of what my compiler is doing, and I wonder whether I found a bug in the compiler... or in my understanding of the C language.
My understanding is that:
- 1UL == ULONG_MAX
, and this is safe since the overflow behavior of unsigned numbers is well defined(- 1UL) * 1.0f
involves the conversion of the left operand to float, and this conversion preserves the value (namely ULONG_MAX
) except for rounding errorsSo far my compiler agrees, unless 1UL
comes from a variable. Here is my test program, with its output as 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 cannot make sense of the last output. I tried various optimization levels, and various language standards (C90, C99 and C11) with identical results. Anyone a clue?
Environment: gcc 4.8.1 / Ubuntu Linux 14.04 / x86-64 (I32LP64)
Edit: I just noticed that my question may be a duplicate of combination of unary minus and float conversion.
The minimum value that can be stored in unsigned long long int is zero.
long long int data type in C++ is used to store 64-bit integers. It is one of the largest data types to store integer values, unlike unsigned long long int both positive and negative. Some properties of the long long int data type are: Being a signed data type, it can store positive values as well as negative values.
This seems to be a bug in gcc 4.8. I have the same behavior as you with 4.8, but gcc 4.9 and clang show the corrected behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With