Glenn Howe writes of an anomaly in Visual Studio 2005’s C++ compiler:
… I discovered today (Friday) that if you compile something like:
double x = (false) ? 0 : 1.4;
that x will not equal 1.4 as most people (and the gcc compiler) would think, but rather it will equal 1.0. Why? Because it sees
0
, interprets it as an integer and decides that if both halves of the:
have to have the same type, then that type will be integer. The fact that this is in the middle of an assignment to double means nothing.
Yes, in fact it does mean nothing; the type of the lvalue on the left-hand side of an assignment expression has no effect on the type of the rvalue on the right-hand side.
He goes on:
I’m not even saying that Visual Studio is wrong. It’s different from gcc which leads to platform specific bugs, …
Well, I was a language lawyer in a previous life, so I can’t let it rest there. (And those of you out there saying “Of course Visual Studio is wrong!” should recall that gcc doesn’t always get it right, either.)
Where were we? The type of the conditional operator, right. To find what that type should be, we have to look at the definition of the operator.
In C99, this is pretty straightforward. Section 6.5.15, which defines the conditional operator, says the result of the expression “is the value of the second or third operand (whichever is evaluated), converted to the type described below”. Looking “below”, it further says when you have two operands of arithmetic type, the result type is the type that would be determined by the “usual arithmetic conversions” applied to the two operands.
Now a simple jump to section 6.3.1.8, which defines the “usual arithmetic conversions”, tells us: “… if the corresponding real type of either operand is double
, the other operand is converted, without change of type domain, to a type whose
corresponding real type is double
.”
OK, so that’s not completely straightforward, talking about “real types” and “type domains”, but basically we have two numbers, and if one of them is double the other is converted to double, and so that’s that; the type of the expression should be double, as we’d expect, and so Visual Studio 2005 is wrong.
If we’re in C.
C++ is more complicated.
(What a shock, right?)
Well, C++ has to allow for the possibility that either or both operand is a class type, and if so can it be converted to the other’s type, blah blah blah (section 5.16, if you’re following along at home).
Since we don’t have class type operands, we go on, applying the “standard conversions” to the operands (none of which apply here), and then, if “the second and third operands have arithmetic or enumeration type[,] the usual arithmetic conversions are performed to bring them to a common type, and the result is of that type.”
Hey, that was pretty simple after all. No, wait: are the usual arithmetic conversions the same in C++ as they are in C? Good question; let me see… (flip, flip, …) here we are, clause 5: yes, they are.
So from where I sit, Visual Studio 2005 is wrong in C++, too.
Wrong on conditional operators.
Wrong for America.
(I can’t wait for this election to be over…)
Comments closed