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

发布于 2024-11-09 18:43:48 字数 590 浏览 2 评论 0原文

我有以下 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;
}

据我所知,两个代码摘录应该是相同的。

I have the following C code:

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

a, b, A1, A2 and B1 are all of type unsigned char. A1, A2 and B1 are all constants.

When compiling under VC++ I see the following warning:

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

I don't understand this warning - none of the variables are of type int. Presumably some kind of implicit conversion is happening, but why?

Strangely, the following code (which is functionally identical) compiles with no warnings:

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

So far as I'm aware, the two code extracts should be identical.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

对你而言 2024-11-16 18:43:48

在 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的范围内。 ?: 的情况更为复杂,因此编译器可能会恢复到通用行为并发出警告。

In C language arithmetic arguments of ternary ?: operator are subjected to usual arithmetic conversions, i.e. they are promoted to int before any further computations are performed. It doesn't really matter whether they are constants or not. What matters is that they have type unsigned char (as you said) and unsigned char under ?: is always promoted first. Basically, C language never performs any computations in types smaller than int. Everything smaller is converted to int first.

This is what happens in your case as well. Basically, your

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

is interpreted by C language as

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

and this is why you get the warning. Again, the fact that A1 and A2 are constants plays no role whatsoever.

The

a = A1;

does not subject the right-hand side to integral promotion, which is why there's no warning here. Moreover, in this trivial case (direct assignment) even if A1 was explicitly declared as an int constant, most compilers would not issue a warning if they could see that the constant is in range of the target type unsigned char. The case with ?: is more complicated, so the compilers might revert to the generic behavior and issue a warning.

つ低調成傷 2024-11-16 18:43:48

尽管功能相同,但这两个代码并不完全相同。

你看,当你使用三元运算符时,这就是 条件 ? true_value : false_value,编译器尝试在值之间推断出最佳的可能类型。

由于 A1 和 A2 是常量(正如您在 OP 中所述),编译器将其位置替换为实际值,完全忽略数据类型,将两者呈现为整数。

因此需要转换结果,如下所示:

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

Although functionally the same, both codes are not quite equals.

You see, when you use a ternary operator, that is the condition ? true_value : false_value, the compiler tries to infer between the values the best possible type.

Because A1 and A2 are constant (as you state in the O.P.) the compiler replaces their position by their actual values, ignoring completely the data type, rendering both as integers.

Hence the need to cast the result, as such:

a = (unsigned char)((b == B1) ? A1 : A2);
挖鼻大婶 2024-11-16 18:43:48
  a = (unsigned char)((b == B1) ? A1 : A2);

我相信这是因为子语句中没有右值——它们在词法分析器中自动转换为 int 。上面的代码应该解决警告消息并且对结果代码没有影响。

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

I believe this is because there is no rvalues in the sub statements -- they get auto converted to int in the lexer. The code above should solve the warning message and have no effect on the resulting code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文