С 条件下的类型转换

С typecasting in conditions

有一个简单的例子:

unsigned a = -5;
int b = 5;
if (a + b <= -1){
...
}

a+b 转换为哪种类型?要签名还是不签名? C 标准中是否注明或编译器将决定做什么?

由于通常的算术转换,如果两个对象具有相同的秩,则将有符号整数类型的对象转换为无符号整数类型。

来自 C 标准(6.3.1.8 常用算术转换)

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

和(6.5.8 关系运算符)

3 If both of the operands have arithmetic type, the usual arithmetic conversions are performed.

所以在这种情况下

if (a + b <= -1){

操作数 a + b-1 都转换为类型 unsigned int.

也就是说 a 的类型为 unsigned int,表达式 a + b 的类型也为 unsigned int。由于表达式 a + b 的类型为 unsigned int 然后表达式 -1 也将具有类型 unsigned int (-1 将被转换为类型 unsigned int).

因此 if 语句的条件将计算为逻辑 true

首先,注意你的术语:

To which type will cast a+b?

转换是显式转换(例如(int)(a))...这是隐式转换!

但是 C 不是一门很棒的语言吗...

考虑:

unsigned a = -5;

在将负数分配给无符号变量时,任何合理定义的语言都会抛出错误...

进一步考虑 ( unsigned int + signed int ):OP 不是第一个,也不会是最后一个被 C 语言中的隐式类型提升搞糊涂的人——其中一些甚至比这更不明显。 .. 答案是这将导致 unsigned int (unsigned + signed = unsigned).

然后是潜在的 Heisenbug(and/or 可能是薛定谔的错误):

if ( unsigned int <= -1 )

根据定义,无符号整数不能小于零,因此生成的 IF 子句无法访问,很可能会被优化掉。但是,-1 实际上会被提升为 unsigned integer 作为 UINT_MAX,因此这变成了 if ( unsigned int <= UINT_MAX ),这当然是总是 true,你有一个无条件条件。

当然,您可能并不真正关心这是无条件为真、无条件为假还是错误答案...

但大多数时候,这很重要...那么,您如何保护自己?

MISRA C 引入了 基本类型模型 的概念,它具有保护您免受意外类型转换影响的指南 - 本书的第 8.10 节(包括一些规则)加上两个附录。

编辑: <= 根据 OP 不只是 < ;-)

(有关从属关系,请参阅个人资料)