在 if 语句比较中,无符号变为有符号?

发布于 2024-10-03 07:12:40 字数 828 浏览 0 评论 0原文

我在这个网站上搜索了答案,发现了许多对无符号/有符号比较的响应,但这个问题是只比较无符号参数,但它仍然很有趣。

以下代码的问题在于,第一个 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 技术交流群。

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

发布评论

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

评论(4

つ低調成傷 2024-10-10 07:12:40

在表达式中:

if( (u16_varLow - u16_varHigh) > (unsigned short)5 )  

(u16_varLow - u16_varHigh) 将提升为 int 并计算为 -65525。解决您的问题的方法是转换为无符号类型,就像您在“是否输入”代码中所做的那样。

s16_Res1 = u16_varLow - u16_varHigh; 产生 11 的原因是减法结果 -65525 不适合短路。

In the expression:

if( (u16_varLow - u16_varHigh) > (unsigned short)5 )  

(u16_varLow - u16_varHigh) will be promoted to an int 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.

空城旧梦 2024-10-10 07:12:40

在其他答案中,我们已经看到,

u16_varLow - u16_varHigh

对于您来说(16 位 short 和 32 位 int)相当于

(int)u16_varLow - (int)u16_varHigh

,因此它的结果是 int > 值-65525。因此,该赋值

s16_Res1 = u16_varLow - u16_varHigh; 

相当于

s16_Res1 = -65525;

在您的 16 位 short 情况下产生“未定义的行为”。您只是不幸,您的编译器决定分配 11 。 (不幸的是,因为我认为尽早失败会更好。)

与此相反的是,

u16_Res1 = -65525; 

这是一个有效的赋值,因为 u16_Res1 是无符号类型,并且无符号类型的算术是以 2 的适当幂为模。

In the other answers we have seen that

u16_varLow - u16_varHigh

for you (with 16 bit short and 32 bit int) is equivalent to

(int)u16_varLow - (int)u16_varHigh

and thus its result is the int value -65525. Thus the assignment

s16_Res1 = u16_varLow - u16_varHigh; 

is equivalent to

s16_Res1 = -65525;

which in your case of 16 bit short yields "undefined behavior". You are just unlucky that your compiler decides to assign 11, instead. (Unlucky because I think that it is better to fail early.)

In contrast to that

u16_Res1 = -65525; 

is a valid assignment since u16_Res1 is of an unsigned type and arithmetic of unsigned types is modulo the appropriate power of two.

飘然心甜 2024-10-10 07:12:40

在“通常的算术转换”中,小于 int 的类型在用于大多数表达式之前会被提升为 intunsigned int。规则是,如果int可以表示较小类型的所有值,则将其提升为int;否则它会被提升为unsigned int。这通常被认为是一个缺点,因为在许多情况下,它会导致 unsigned charunsigned Short 值提升为 int

这正是您所看到的 - u16_varLowu16_varHigh 以及 (unsigned Short)5 全部提升为 int 在减法和比较之前,然后使用 int 进行。如果您希望确定表达式将使用无符号算术,则必须使用unsigned int而不是unsigned Short

if( ((unsigned)u16_varLow - (unsigned)u16_varHigh) > 5U )

In the "usual arithmetic conversions", types smaller than int are promoted to either int or unsigned int before they are used in most expressions. The rule is that if int can represent all the values of the smaller type, then it is promoted to int; otherwise it is promoted to unsigned int. This is often considered something of a wart, because in many cases it causes unsigned char and unsigned short values to be promoted to int.

This is exactly what you're seeing - u16_varLow and u16_varHigh and (unsigned short)5 are all promoted to int before the subtraction and comparison, which then happen using int. If you wish to be certain that an expression will use unsigned arithmetic, you must do it in unsigned int, not unsigned short:

if( ((unsigned)u16_varLow - (unsigned)u16_varHigh) > 5U )
未央 2024-10-10 07:12:40

第一个 if( (u16_varLow - u16_varHigh) > (unsigned Short)5 ) 永远不会通过,因为 (u16_varLow - u16_varHigh) 返回负数,因为它被处理作为整数。第二个将相同的负数转换为无符号短整型,这就是它通过的原因。

注意 - 您知道这一切都依赖于平台,对吧? shortint等的大小取决于具体平台。

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.

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