条件运算符:从'int'转换为'unsigned char',可能会丢失数据

时间:2011-05-24 18:01:51

标签: c++ conditional-operator

我有以下C代码:

a = (b == B1) ? A1 : A2;

abA1A2B1都属于unsigned char类型。 A1A2B1都是常量。

在VC ++下编译时,我看到以下警告:

warning C4244: '=' : conversion from 'int ' to 'unsigned char ', possible loss of data

我不明白这个警告 - 所有变量都不是int类型。据推测,某种隐式转换正在发生,但为什么呢?

奇怪的是,以下代码(功能相同)编译时没有警告:

if (b == B1) {
  a = A1;
} else {
  a = A2;
}

据我所知,这两个代码提取应该是相同的。

3 个答案:

答案 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;

这就是你收到警告的原因。同样,A1A2是常量的事实不起任何作用。

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。上面的代码应解决警告消息,并且不会对生成的代码产生影响。