有一个简单的例子:
unsigned a = -5;
int b = 5;
if (a + b <= -1){
...
}
将转换为哪种类型a+b?要签名还是未签名?是否在 C 标准中注明或编译器将决定做什么?
有一个简单的例子:
unsigned a = -5;
int b = 5;
if (a + b <= -1){
...
}
将转换为哪种类型a+b?要签名还是未签名?是否在 C 标准中注明或编译器将决定做什么?
由于通常的算术转换,如果两个对象具有相同的等级,则有符号整数类型的对象将转换为无符号整数类型。
来自 C 标准(6.3.1.8 常用算术转换)
否则,如果无符号整数类型的操作数的等级大于或等于另一个操作数类型的等级,则将有符号整数类型的操作数转换为无符号整数类型的操作数的类型。
和(6.5.8 关系运算符)
3 如果两个操作数都具有算术类型,则执行通常的算术转换。
所以在这种情况下
if (a + b <= -1){
两个操作数a + b和-1都转换为类型unsigned int。
即 asa有类型unsigned intthen 并且表达式a + b也有 type unsigned int。由于表达式a + b具有unsigned intthen 类型,因此表达式-1也将具有 unsigned int 类型(-1将转换为该类型的最大值unsigned int)。
因此 if 语句的条件将评估为逻辑true.
首先,请注意您的术语:
将 a+b 转换为哪种类型?
强制转换是显式转换(例如(int)(a))...这是隐式转换!
但是C不是一门很棒的语言吗...
考虑:
unsigned a = -5;
将负数分配给无符号变量时,任何合理定义的语言都会引发错误......
进一步考虑( unsigned int + signed int ):OP 不是第一个,也不会是最后一个,被 C 语言中的隐式类型提升弄糊涂了——其中一些甚至比这更不明显......答案是这将导致一个unsigned int(无符号+有符号=无符号)。
然后是潜在的 Heisenbug(和/或可能是薛定谔的错误):
if ( unsigned int <= -1 )
根据定义,无符号整数不能小于零,因此结果 IF子句是不可访问的,并且很可能被优化掉。但是,-1实际上将被提升为unsigned integerUINT_MAX ,因此它变为if ( unsigned int <= UINT_MAX ),当然总是true,并且您有一个无条件的条件。
当然,您可能并不真正关心这是无条件正确、无条件错误还是错误答案……
但大多数时候,这很重要……那么,你如何保护自己?
MISRA C 引入了基本类型模型的概念,它提供了保护您免受意外类型转换的指导——本书的第 8.10 节(包括一些规则)和两个附录。
编辑: <=不只是<按照 OP ;-)
(见隶属关系简介)