我有以下C代码:
a = (b == B1) ? A1 : A2;
a
,b
,A1
,A2
和B1
都属于unsigned char
类型。 A1
,A2
和B1
都是常量。
在VC ++下编译时,我看到以下警告:
warning C4244: '=' : conversion from 'int ' to 'unsigned char ', possible loss of data
我不明白这个警告 - 所有变量都不是int
类型。据推测,某种隐式转换正在发生,但为什么呢?
奇怪的是,以下代码(功能相同)编译时没有警告:
if (b == B1) {
a = A1;
} else {
a = A2;
}
据我所知,这两个代码提取应该是相同的。
答案 0 :(得分:4)
在C语言中,三元?:
运算符的算术参数经常进行算术转换,即在执行任何进一步的计算之前将它们提升为int
。它们是否是常数并不重要。重要的是,他们的unsigned char
类型(正如您所说)unsigned char
下的?:
始终是首先推广的。基本上,C语言从不以小于int
的类型执行任何计算。较小的一切首先转换为int
。
这也是你的情况。基本上,你的
a = (b == B1) ? A1 : A2;
被C语言解释为
a = ((int) b == (int) B1) ? (int) A1 : (int) A2;
这就是你收到警告的原因。同样,A1
和A2
是常量的事实不起任何作用。
a = A1;
不会对右侧进行整体推广,这就是为什么这里没有警告。此外,在这个简单的情况下(直接赋值),即使A1
被明确声明为int
常量,大多数编译器也不会发出警告,如果他们可以看到常量在目标类型的范围内unsigned char
。 ?:
的情况更复杂,因此编译器可能会恢复为通用行为并发出警告。
答案 1 :(得分:3)
虽然在功能上相同,但两个代码并不完全相同。
您可以看到,当您使用三元运算符时,即condition ? true_value : false_value
,编译器会尝试在值之间推断出最佳类型。
因为A1和A2是常量(正如你在O.P.中所说的那样),编译器用它们的实际值替换它们的位置,完全忽略数据类型,将它们都作为整数呈现。
因此需要投射结果:
a = (unsigned char)((b == B1) ? A1 : A2);
答案 2 :(得分:2)
a = (unsigned char)((b == B1) ? A1 : A2);
我相信这是因为子语句中没有rvalues - 它们在词法分析器中自动转换为int。上面的代码应解决警告消息,并且不会对生成的代码产生影响。