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



我不明白为什么编译器在通过(?:)分配不兼容指针时不发出警告,而在直接分配时发出警告。

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

test.c:在函数'main'中:test.c:8:4:警告:分配给来自不兼容指针类型的"uint32_t*"{aka"unsigned int*"}"uint32_t**"{aka"unsigned int**"}[-Wincompatible指针类型]8|a=数组;|^

#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. 。。。否则,一个操作数是指向void的指针或void的限定版本,在这种情况下,结果类型是指向void的适当限定版本

函数malloc返回类型为void *的指针。因此,带有条件运算符的表达式的类型是void *。并且CCD_ 11类型的指针可以被分配给任何其他对象类型的指针。

来自C标准(6.3.2.3指针(

1指向void的指针可以转换为指向对象类型。指向任何对象类型的指针都可以转换为指针指向空,然后再次返回;结果应与原始指针。

事实上你有

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

最新更新