unsigned long 0< -1?

时间:2009-09-12 16:37:05

标签: c

我不懂这个!

#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

要么两者都失败,要么两者都失败。我用gcc 4&amp; 4.2

4 个答案:

答案 0 :(得分:13)

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

答案 1 :(得分:12)

C语言为许多操作员执行“常用算术转换” - 转换在C99标准的6.3.1.8中列出。对于整体操作数,会执行首次促销,这就是造成问题的原因。 6.3.1.1(算术操作数/布尔值,字符和整数)中概述了这些促销,其中包括:

  

如果int可以表示原始类型的所有值,则该值将转换为int;否则,它将转换为unsigned int。这些被称为整数促销。所有其他类型都不会被整数促销更改。

促销仅适用于排名小于intunsigned int(或位域)的整数类型的对象或表达式。

所以在你的外表中:

t1 < t2-1 

即使变量为unsigned short,它们也会提升为int,因为在您的平台上int可以代表unsigned short的所有值。因此,使用int类型评估表达式,并且不会出现下溢 - 表达式的t2-1部分最终为负数。

在表达式中:

s1 < s2-1

unsigned long类型未被提升,因为它们的排名高于int / unsigned int,因此表达式使用无符号算术进行评估(带有下溢值)减法),s2-1子表达式的计算结果非常大,而不是负数。

如评论中指出的那样,如果平台的int实现为16位类型(例如允许 - 例如MS-DOS),则unsigned short的促销将是{ {1}}代替unsigned int,因为int无法表示int的所有值(unsigned short必须至少为16位)。在这种情况下,两个unsigned short语句都将评估为true。

答案 2 :(得分:3)

正如您所发现的那样,只要您在不同类型之间操作,C强制并不总是显而易见的。 t2是u16,1int(大概是32位),所以t2-1就是这种“不同类型之间的操作”并导致对int的整体强制(因为它比你的“更长”......)。后来,由于s2和1都是32位(虽然具有不同的符号),但整体强制是无符号长。因此,所涉及的类型的大小确实有助于确定整体强制的签名。

我建议避免使用混合签名(理想情况下也是混合大小!)操作(通过强制转换或特殊字面符号表示文字,例如1,否则会int类型并使你的生活更具潜力复杂且您的代码可能无法移植; - )。

答案 3 :(得分:0)

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

请注意,以下将转到printf,因为现在再次在16位无符号空间中进行比较:

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