I gone through this question -
why the result of : 1 ? (int *)0 : (void *)0
differs to the result of :
1 ? (int *)0 : (void *)1
So effeffe already answered on why the two expressions differ:
1 ? (int *) 0 : (void *) 0 // yield (int *) 0
1 ? (int *) 0 : (void *) 1 // yield (void *) 0
To answer this question now:
How to check the result ?
With gcc
you can use typeof
extension and __builtin_types_compatible_p
builtin function:
// The two expressions differ
printf("%d\n", __builtin_types_compatible_p(typeof(1 ? (int *) 0 : (void *) 0), typeof(1 ? (int *) 0 : (void *) 1)));
// First expression yield (int *) 0
printf("%d\n", __builtin_types_compatible_p(typeof((int *) 0), typeof( 0 ? (int *)0 : (void *)0 )));
// Second expression yield (void *) 0
printf("%d\n", __builtin_types_compatible_p(typeof((void *) 0), typeof( 1 ? (int *)0 : (void *)1 )));
The only difference is in types: the first one returns an int *
, the second one returns a void *
.
From C11 standard, §6.5.15 Conditional operator, ¶6:
If both the second and third operands are pointers or one is a null pointer constant and the other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers of the types referenced by both operands. Furthermore, if both operands are pointers to compatible types or to differently qualified versions of compatible types, the result type is a pointer to an appropriately qualified version of the composite type; if one operand is a null pointer constant, the result has the type of the other operand; otherwise, one operand is a pointer to
void
or a qualified version ofvoid
, in which case the result type is a pointer to an appropriately qualified version ofvoid
.
(emphasis mine)
Remember that a pointer to non-void
cannot be a null pointer constant but just a null pointer. C11 §6.3.2.3 Pointers, ¶3:
An integer constant expression with the value 0, or such an expression cast to type
void *
, is called a null pointer constant.66) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.66) The macro
NULL
is defined in<stddef.h>
(and other headers) as a null pointer constant; see 7.19.
So, here:
1 ? (int *) 0 : (void *) 0
(int *) 0
is just a null pointer while (void *) 0
is a null pointer constant, so the result has type int *
("if one operand is a null pointer constant, the result has the type of the other operand").
while here:
1 ? (int *) 0 : (void *) 1
there are no null pointer constants (only a null pointer, the first one), so the result has the composite type void *
("if both operands are pointers to compatible types or to differently qualified versions of compatible types, the result type is a pointer to an appropriately qualified version of the composite type").
The results have different types but they are both null pointers. Also note that the result is never 0
as you say in your question, it's always a pointer.
Unfortunately there is no standard way to see the difference in C, C++ has some support about it (typeinfo
) but results are different there.
Where we can use such type of expression?
I can't think about a useful and concrete use of this obscure corner of the language.