基于三元运算符 (?:) 的赋值避免了 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 条件运算符)
- ... 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) );
我无法理解为什么编译器在通过 (?:) 分配不兼容的指针时不发出警告,但在直接分配时发出警告。
编译器在这种情况下发出警告:
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 条件运算符)
- ... 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) );