Confusion in ternary operator and typecasting

后端 未结 2 1047
半阙折子戏
半阙折子戏 2021-01-05 08:42

I gone through this question -

why the result of : 1 ? (int *)0 : (void *)0
differs to the result of : 1 ? (int *)0 : (void *)1

相关标签:
2条回答
  • 2021-01-05 08:56

    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  )));
    
    0 讨论(0)
  • 2021-01-05 09:05

    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 of void, in which case the result type is a pointer to an appropriately qualified version of void.

    (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.

    0 讨论(0)
提交回复
热议问题