Home > Software design >  Ternary Operator (?:) based assignment avoids type check in C
Ternary Operator (?:) based assignment avoids type check in C

Time:01-20

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

CodePudding user response:

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.

CodePudding user response:

From the C Standard (6.5.15 Conditional operator)

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

The function malloc returns a pointer of the type void *. So the type of the expression with the conditional operator is void *. And a pointer of the type void * can be assigned to a pointer of any other object type.

From the C Standard (6.3.2.3 Pointers)

1 A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.

In fact you have

a = ( void * )(b >= 8 ? array : malloc(8) );
  •  Tags:  
  • Related