Reputation: 615
Lets say we have the following expression:
(x>y) ? printf("type of int") : func_string()
So what do we have here?
x>y -> true -> printf("type of int") -> the type of the expression is int (because printf function is an int type function).
or
x>y -> false -> calls func_string() function which for the purpose of the question, returns a string.
The conclusion is that we have only 2 options for the outcome of this expressions:
an int function (prinf)
OR a string function (func_string)
.
Which means there are 2 possible types for the expressions.
However, the compiler can't really wait until the runtime to get the type of the expression, the compiler can't really compile the code while not being sure if the expression's type is an int or a string, so are we gonna get a compile error if we will try to run this sort of code, with 2 different types for the 2 outcomes of the conditional operator.
Upvotes: 2
Views: 200
Reputation: 213960
The standard C17 6.5.15 specifies that the operands must behave according to this:
Constraints
The first operand shall have scalar type.
One of the following shall hold for the second and third operands:
— both operands have arithmetic type;
— both operands have the same structure or union type;
— both operands have void type;
— both operands are pointers to qualified or unqualified versions of compatible types;
— one operand is a pointer and the other is a null pointer constant; or
— one operand is a pointer to an object type and the other is a pointer to a qualified or
unqualified version of void.
In your example, (x>y) ? printf("type of int") : func_string();
, printf
returns type int
which is an arithmetic type. func_string()
supposedly returns a char*
, which is a pointer type. This use case doesn't match any of the above listed valid scenarios, since the types are not compatible.
And so the compiler reports that the code isn't valid C. Some examples of compiler diagnostics:
icc:
operand types are incompatible ("int" and "char *")
gcc:
pointer/integer type mismatch in conditional expression
In case the 2nd and 3rd operands had been compatible or at least both arithmetic types (one float
and one int
etc), then this rule from 6.5.15 applies:
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. If both the operands have structure or union type, the result has that type. If both operands have void type, the result has void type.
To understand that part, you need to understand the meaning of the usual arithmetic conversions, see Implicit type promotion rules
The bottom line is that ?:
is not some glorified if-else
replacement, but a rather peculiar operator that comes with lots of special rules. ?:
also has very few valid use-cases in real C code, one of the few valid uses for it is certain function-like macros.
Upvotes: 9