On Wed, Feb 2, 2022 at 11:42 PM David Laight <David.Laight@xxxxxxxxxx> wrote: > > The compiler needs to find a 'compatible type' either for: > (void *)x and (int *)8 > or for: > (void *)0 and (int *)8 > > In the former it is 'void *' and the latter 'int *' because the (void *)0 > is NULL and thus a valid 'int *' pointer. I think you are trying to come up with an explanation of how it works based on compiler outputs (it makes sense to think that the compiler has to find some reasonable "common" type). But the conditional operator works case-by-case, slightly differently depending on what kind of operands you give. In the two cases involved, there is no "finding a compatible type" / promotions going on -- the standard gives explicitly that it is a pointer to void (former case), and the type of the other operand (latter case). The value is still decided by the condition. e.g. https://godbolt.org/z/zzE8dc7Ye 0 ? void pointer (1) : pointer to object type (42) = (void *) 0x2a 1 ? void pointer (1) : pointer to object type (42) = (void *) 0x1 0 ? null pointer constant (0) : pointer (42) = ( int *) 0x2a 1 ? null pointer constant (0) : pointer (42) = ( int *) (nil) > In any case suggesting that it is based on the value before the ? is bogus. What Rasmus was saying is that which value is selected still depends on the condition, because the last paragraph of the explanation in the commit is wrong. It should be something like: - The ultimate comparison to "sizeof(int)" reduces to either: sizeof(int) == sizeof(*(int *)0) (x was a constant expression) sizeof(int) == sizeof(*(void *)0) (x was not a constant expression) Cheers, Miguel