无符号整数差异的意外结果

时间:2014-11-18 02:38:11

标签: c

我很惊讶这个函数为dif1和dif2

产生不同的值
void test()
{
    unsigned int x = 0, y = 1;
    long long dif1 = x - y;
    long long dif2 = (int)(x - y);
    printf("dif = %lld %lld",dif1,dif2);
}

这是正确的行为吗?在dif1计算中,它首先将32位无符号差异提升为64位无符号值,然后添加符号。是标准行为,不是由语言指定,还是编译器错误?第二种形式是否保证产生-1,或者直到编译器实现?我想最安全的结构是: long long dif3 =(long long)x - (long long)y;

2 个答案:

答案 0 :(得分:4)

如果我们假设long long宽于unsigned int,那么第一个肯定是定义的。如果不是,则分配给出与答案的第二部分相同的问题。

long long dif1 = x - y;

无符号整数将换行,并且您将获得可以存储在unsigned int中的最大值。

  

6.2.5 p9:涉及无符号操作数的计算永远不会溢出,   因为无法用结果无符号整数类型表示的结果是   减少模数可以是最大值的数字   由结果类型表示。


至于第二个

long long dif2 = (int)(x - y);

它是实现定义的:

  

6.3.1.3 p3:否则,新类型已签名,其值无法表示;无论是   结果是实现定义的或引发实现定义的信号。

在这种情况下,unsigned int的最大值无法在上述规则生效的int中表示。

答案 1 :(得分:1)

没有什么可以令人惊讶的。

unsigned int x = 0, y = 1;
long long dif1 = x - y;
long long dif2 = (int)(x - y);

第二个与第一个有一点不同:

施放到signed 如果可能,强制转换定义为保留值(UINT_MAX大于INT_MAX时不可能),否则实现定义(尽管允许陷阱)

如果我们在演员表上有2s-complement(可能),则演员的结果为-1

接下来,我们有一个更宽泛的签名类型的赋值,它总是保持值。