在 if 语句比较中,无符号变为有符号?
我在这个网站上搜索了答案,发现了许多对无符号/有符号比较的响应,但这个问题是只比较无符号参数,但它仍然很有趣。
以下代码的问题在于,第一个 if
语句没有发生(“hello”),而第二个语句(“world”)却发生了。我将其解释为在 if 语句内完成的计算会生成负数,但使用保存到变量的结果完成的完全相同的计算不会生成负数(即使结果被保存到有符号变量)。
使用的编译器是gcc 4.4。
unsigned short u16_varHigh;
unsigned short u16_varLow;
unsigned short u16_Res1;
signed short s16_Res1;
u16_varHigh = 0xFFFF;
u16_varLow = 10;
u16_Res1 = u16_varLow - u16_varHigh; // response is 11 as expected
s16_Res1 = u16_varLow - u16_varHigh; // response is 11 as expected
// Does not enter
if( (u16_varLow - u16_varHigh) > (unsigned short)5 )
{
printf( "hello" );
}
// Does enter
if( (unsigned short)(u16_varLow - u16_varHigh) > 5 )
{
printf( "world" );
}
任何人都可以为我解释一下这一点,并可能提出一个解决方案来修复,以便第一个 if
语句也能正常工作?
I have searched this site for an answer and found many responses to unsigned/signed comparison but this problem is that only unsigned parameters are compared but still it works funny.
The problem with the following code is that the first if
-statment does not happen ("hello") where as the second ("world") does. This I have interpreted as the calculation that is done inside the if
-statment generates a negative number but the exact same calculation done with the result saved to a variables does not (even though the result is being saved to a signed variable).
The compiler used is gcc 4.4.
unsigned short u16_varHigh;
unsigned short u16_varLow;
unsigned short u16_Res1;
signed short s16_Res1;
u16_varHigh = 0xFFFF;
u16_varLow = 10;
u16_Res1 = u16_varLow - u16_varHigh; // response is 11 as expected
s16_Res1 = u16_varLow - u16_varHigh; // response is 11 as expected
// Does not enter
if( (u16_varLow - u16_varHigh) > (unsigned short)5 )
{
printf( "hello" );
}
// Does enter
if( (unsigned short)(u16_varLow - u16_varHigh) > 5 )
{
printf( "world" );
}
Can anyone explain this for me and perhaps come up with a solution for a fix so that the first if
-statement works as well?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在表达式中:
(u16_varLow - u16_varHigh)
将提升为int
并计算为 -65525。解决您的问题的方法是转换为无符号类型,就像您在“是否输入”代码中所做的那样。s16_Res1 = u16_varLow - u16_varHigh;
产生 11 的原因是减法结果 -65525 不适合短路。In the expression:
(u16_varLow - u16_varHigh)
will be promoted to anint
and evaluate to -65525. The fix for your problem is to cast to an unsigned type, like you do in the "Does enter"-code.The reason
s16_Res1 = u16_varLow - u16_varHigh;
yields 11 is that the result of the subtraction, -65525, doesn't fit in a short.在其他答案中,我们已经看到,
对于您来说(16 位
short
和 32 位int
)相当于,因此它的结果是
int
> 值-65525
。因此,该赋值相当于
在您的 16 位
short
情况下产生“未定义的行为”。您只是不幸,您的编译器决定分配11
。 (不幸的是,因为我认为尽早失败会更好。)与此相反的是,
这是一个有效的赋值,因为
u16_Res1
是无符号类型,并且无符号类型的算术是以 2 的适当幂为模。In the other answers we have seen that
for you (with 16 bit
short
and 32 bitint
) is equivalent toand thus its result is the
int
value-65525
. Thus the assignmentis equivalent to
which in your case of 16 bit
short
yields "undefined behavior". You are just unlucky that your compiler decides to assign11
, instead. (Unlucky because I think that it is better to fail early.)In contrast to that
is a valid assignment since
u16_Res1
is of an unsigned type and arithmetic of unsigned types is modulo the appropriate power of two.在“通常的算术转换”中,小于
int
的类型在用于大多数表达式之前会被提升为int
或unsigned int
。规则是,如果int
可以表示较小类型的所有值,则将其提升为int
;否则它会被提升为unsigned int
。这通常被认为是一个缺点,因为在许多情况下,它会导致unsigned char
和unsigned Short
值提升为int
。这正是您所看到的 -
u16_varLow
和u16_varHigh
以及(unsigned Short)5
全部提升为int
在减法和比较之前,然后使用int
进行。如果您希望确定表达式将使用无符号算术,则必须使用unsigned int
,而不是unsigned Short
:In the "usual arithmetic conversions", types smaller than
int
are promoted to eitherint
orunsigned int
before they are used in most expressions. The rule is that ifint
can represent all the values of the smaller type, then it is promoted toint
; otherwise it is promoted tounsigned int
. This is often considered something of a wart, because in many cases it causesunsigned char
andunsigned short
values to be promoted toint
.This is exactly what you're seeing -
u16_varLow
andu16_varHigh
and(unsigned short)5
are all promoted toint
before the subtraction and comparison, which then happen usingint
. If you wish to be certain that an expression will use unsigned arithmetic, you must do it inunsigned int
, notunsigned short
:第一个
if( (u16_varLow - u16_varHigh) > (unsigned Short)5 )
永远不会通过,因为(u16_varLow - u16_varHigh)
返回负数,因为它被处理作为整数。第二个将相同的负数转换为无符号短整型,这就是它通过的原因。注意 - 您知道这一切都依赖于平台,对吧?
short
、int
等的大小取决于具体平台。The first one,
if( (u16_varLow - u16_varHigh) > (unsigned short)5 )
will never pass, as(u16_varLow - u16_varHigh)
returns negative number, because it's treated as an integer. The second one casts the same negative number, to unsigned short, that's why it passes.Note - you know that all this is platform-dependent, right? The size of
short
,int
, etc. depends on the concrete platform.