2009-09-12 127 views
8

我不明白这个!unsigned long 0 <-1?

#include <stdio.h> 

int main() 
{ 
    unsigned short t1 = 0, t2 = 0; 

    if(t1 < t2-1) 
     printf(" t1 < t2-1\n"); 

    unsigned long s1 = 0, s2 = 0; 

    if(s1 < s2-1) 
     printf(" s1 < s2-1\n"); 
} 

这导致:

s1 < s2-1 

要么两者都应该失败或两者没有。我试过这与海湾合作委员会4 & 4.2

+0

〜nairboon:我希望你不介意编辑。我替换的代码在功能上是相同的,但可以复制/粘贴到编辑器中并进行编译而不用更改。 – 2009-09-12 16:51:25

+1

请注意,这个结果不能保证是结果。在int存储与short相同的值范围的机器上(我认为16位机器将会),你会看到两个ifs的输出,因为升级会转换为unsigned int,而不是int。 – 2009-09-12 18:37:11

回答

12

C语言进行了许多运营商的“通常的算术转换” - 的转换在C99标准的6.3.1.8中概述。对于整数操作数,首先进行促销活动,这是造成您的问题的原因。促销在6.3.1.1(算术操作数/布尔,字符和整数)中概述,其中包括:

如果int可以表示原始类型的所有值,则该值将转换为INT;否则,它被转换为一个unsigned int。这些被称为整数促销。所有其他类型均不受整数升级的影响。

的优惠仅应用于物体或表达与整数类型与秩小于intunsigned int(或位域)。

所以在你exression:

t1 < t2-1 

即使变量unsigned short他们晋级到int,因为你的平台上int可以代表unsigned short所有的值。因此,使用int类型评估表达式,并且不发生下溢 - 表达式的t2-1部分最终为负1。

在表达式:

s1 < s2-1 

unsigned long类型不促进,因为它们具有比int/unsigned int较高“秩”,所以表达式是使用无符号算术运算(从底流评价减法),并且s2-1子表达式的计算结果为一个非常大的数量,而不是负1.

作为litb在评论所指出的,如果该平台已int实现为一个16位的类型(这是允许的 - MS-DOS为例如),亲因为int将不能代表unsigned shortunsigned short必须至少为16位)的所有值,所以unsigned short的运动将是unsigned int而不是int。在这种情况下,两个if语句将评估为true。

13

Iam不知道,但我怀疑t2-1表达式自动扩展为一个int值。 这里我没有c标准确切的转换规则,但我相信小于int的类型会自动加宽。

+3

+1,在算术表达式中,类型(有符号/无符号)short和(signed/unsigned /)char的对象被*升级为int。 – avakar 2009-09-12 16:44:20

+1

如果你说**'t2' **被转换为int,而不是**'t2-1 **(这样就很清楚转换发生在*减法之前),这个答案会好得多。 – 2009-09-12 18:32:34

3

正如你所发现的,C强制并不总是显而易见的,只要你在不同类型之间进行操作。 t2是u16,1int(大概是32位),所以t2-1就是这样一种“不同类型之间的操作”,并导致整体强制为int(因为它比u16更“长”)。后来,因为s2和1都是32位(尽管签名不同),所以整体强制为无符号长整型。因此,所涉及类型的大小有助于确定整体强制的签名。我建议避免混合签名(并且理想情况下也是混合大小!)操作(通过铸造或文字的特殊文字符号(如1),否则将会有int类型,并使您的生活变得复杂,并且您的代码可能无法移植; - )。

0

-1表示为全1。因此,当解释为无符号时,其值为2^32-1,明显大于0.我猜想第一个比较正在扩展为执行32位有符号算术(可能是因为“1”是一个签署int)。

注意,以下将要抵达的printf,因为比较是再16位无符号空间现在做:

u32 temp = t2 - 1; 
if(t1 < temp) 
    printf(" t1 < t2-1\n"); 
+4

在减法之前,文字1('int'类型)被转换为'unsigned long'。由于对无符号类型的算术总是以'2^k'为模执行,对于类型特定的'k',结果是'2^k-1'。 -1的表示没有涉及(在某些体系结构中并不一定全是1)。 – avakar 2009-09-12 16:57:48

+0

-1的表示形式涉及解释第二部分:为什么无符号long中的0 <-1。 – Yuliy 2009-09-12 19:25:26

+0

不,它不是。像avakar说的那样,'-N' - > unsigned是纯粹的数学运算,只计算'UINT_MAX + 1 - N'。任何地方都没有任何代表。 – 2009-09-12 19:52:35

相关问题