基于三元运算符 (?:) 的赋值避免了 C 中的类型检查

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

我无法理解为什么编译器在通过 (?:) 分配不兼容的指针时不发出警告,但在直接分配时发出警告。

编译器在这种情况下发出警告:

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;
}

以下情况无警告:

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

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

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

环境:

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

表达式(b >= 8) ? array : malloc(8)的类型是void*(因为malloc(8)的类型是void*)。你可以通过做一些无意义的事情并让编译器告诉你来看到这一点:

((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* 可以隐式转换为任何类型的指针,这就是为什么当您将该值赋给 a.

时编译器不会报错的原因

来自 C 标准(6.5.15 条件运算符)

  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.

函数 malloc returns 类型为 void * 的指针。所以带条件运算符的表达式的类型是void *void * 类型的指针可以赋值给任何其他对象类型的指针。

来自 C 标准(6.3.2.3 指针)

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.

事实上你有

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