Reputation: 159
I need to convert a double number to an integer based on a condition, but when I use the ternary operator I get some weird results. I wrote this simple program to test my logic but I cannot understand what's going on.
#include <stdio.h>
int main()
{
double n = 50.0;
printf("%i\n", (int)n);
printf("%i\n", ((1) ? (int)n : n));
printf("%i\n", ((1) ? n : (int)n));
printf("%i\n", ((0) ? (int)n : n));
printf("%i\n", ((0) ? n : (int)n));
return 0;
}
I expected to get the following output:
50
50
0
0
50
But the output I got was:
50
0
0
0
0
Upvotes: 2
Views: 80
Reputation: 780818
When the 2nd and 3rd operands to the ternary operator have different types, they are automatically converted to the same type, using the usual arithmetic conversions. So doing a cast on just one of the operands doesn't have the effect you expect -- (int) n
will be cast back to double
and that will be the type of the ternary expression.
This will then be passed to printf
, and you'll get undefined behavior because you're trying to print a double
using %i
format, which expects an int
.
If you want the type of the argument to depend on the condition, you need to use an ordinary if
. For instance, this is what you were apparently trying to accomplish in your first ternary example:
if (1) {
printf("%i\n", (int) n); // valid
} else {
printf("%i\n", n); // invalid
}
Upvotes: 2
Reputation: 753595
In the standard for the 'conditional operator', it says:
If both the second and third operands have arithmetic type, the result type that would be determined by the usual arithmetic conversions, were they applied to those two operands, is the type of the result.
Since you have int
and double
as the types, the result of the conditional is always double
, so you get whatever garbage you get when you print it with the wrong format — which is invoking undefined behaviour and a bad idea
Upvotes: 1
Reputation: 140540
You have tripped over two dark corners of the C language at once.
Given double n
, the "usual arithmetic conversions" cause (ANYTHING ? (int)n : n)
and (ANYTHING ? n : (int)n)
to both have type double
. That is, if the (int)n
branch is taken, the value n
is converted to int
and then back to double
.
printf("%i\n", (double)whatever)
provokes undefined behavior. This is because printf
relies on its format string to know the types of its variadic arguments. If you tell it to print an int
but you pass a double
it will look in the wrong place for the value to print.
Because of (1), (2) affects all four of the printf
statements containing a ternary expression, not just the ones where the cast-to-int
branch was not taken.
I don't understand what you were trying to accomplish with (condition ? (int)n : n)
, so I can't tell you what you should have done instead.
Upvotes: 1