Oct 25, 2018

Casting Values

I have a scary Halloween story to tell you...

I was running into a bug in my new compiler where large ints where loosing precision. After tracing through my compiler's C++ code for about an hour trying to catch the spot, I came to this function:

int intConstValue() { return _type == kFloat ? _float : _int; }

It took me a bit of starring and then it hit. Something from the deep recesses of C-lore came jumping up.

Do you know the issue?

I won't keep everyone in suspense...

The both sides of trinary operator must return the same type, and in this case I was returning an INT and a FLOAT, so it cast the INT to a FLOAT before returning the value. I didn't notice it until one of my units tests sent large INT's through, larger than a FLOAT can store without loosing precision. Since the function (intConstValue) is returning an INT, I guess I assumed the it would downcast the float, but you know what they say about assuming.

I seem to recall being bitten by a similar bug 20 years ago. I guess I'm good until 2038... just in time for Unix time roll over.

Tramboi

Oct 25, 2018
Maybe you should enable warnings.

Neil

Oct 25, 2018
Did your compiler not give a warning? Or should I say your compiler compiler not give a warning? I guess converting built in types is always acceptable.

As a lazy C++ coder, I never remember the order of operator precedence. So when I come across an unbracketed ternary conditional A==B?C:D, I never know if it's (A==B)?C:D or A==(B?C:D). I had to look it up again.

Ron Gilbert

Oct 25, 2018
I have most warning enable, or at least warning that would have caught this, and nothing.

Ron Gilbert

Oct 25, 2018
Ah... you're right.  I use CMake to build xcode/VS projects and I had the warning flag that checks for int/float conversions set wrong. Oh well... Scary Halloween stories are less scary with warnings turned on.

Nor Treblig

Oct 26, 2018
@Neil: The precedence of this conditional operator is very low, it's on par with assignments.
It's also right to left as you are probably used to with assignments.

IMO it is easy to remember if you think about the purpose of this operator which is all about *conditions*. E.g.
a <= b || c != d ? x : y
The whole condition is evaluated first.

Zak Phoenix McKracken

Oct 26, 2018
The FDIV Pentium bug was real and scary, 20 years ago. 32.2 - 31.1 - 1.1 was not equal to zero...

Alien426

6d ago
@Zak
Where is the division (Floating-point DIVision bug) in "32.2 - 31.1 - 1.1"? You can check for that bug with "4195835 / 3145727" which should return 1.33382...
What you have shown is just a floating-point precision problem. Which still exists. Check out https://floating-point-gui.de
Here are the rules for commenting.