Search code examples
cgccimplicit-conversionconditional-operatorvoid-pointers

Ternary Operator (?:) based assignment avoids type check in C


I am not able to understand why the compiler doesn't warn when assigning incompatible pointers through (?:) but does warn on direct assignment.

Compiler warns in this case:

test.c: In function ‘main’: test.c:8:4: warning: assignment to ‘uint32_t *’ {aka ‘unsigned int *’} from incompatible pointer type ‘uint32_t **’ {aka ‘unsigned int **’} [-Wincompatible-pointer-types] 8 | a = array; | ^

#include <stdint.h>
#include <stdlib.h>

int main(void)
{
    uint32_t *array[10], *a;
    a = array;
}

No warning in the following case:

#include <stdint.h>
#include <stdlib.h>

int main(void)
{
    int b = 8;
    uint32_t *array[10], *a;

    a = (b >= 8) ? array : malloc(8);
}

Environment:

Gcc version 9.3.0
Ubuntu 20.04
compilation cmd: gcc test.c -o test.out

Solution

  • The type of the expression (b >= 8) ? array : malloc(8) is void* (because malloc(8) has the type void*). You can see this by doing something non-sensical and having the compiler tell you:

    ((b >= 8) ? array : malloc(8)) * 5;
    
    <source>:10:36: error: invalid operands to binary * (have 'void *' and 'int')
       10 |     ((b >= 8) ? array : malloc(8)) * 5;
          |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
          |                       |
          |                       void *
    

    void* can be implicitly converted to a pointer of any type, which is why the compiler doesn't complain when you assign that value to a.