-1和~0之间有区别吗?

时间:2014-07-09 09:30:57

标签: c++ c

比较无符号值时,如此测试:

if (pos == (size_t)-1)

这种比较技术上是否与以下内容不同:

if (pos == (size_t)~0)

我不习惯第二种变体。这就是我问这个问题的原因。如果是的话,答案可能会相当直接。

3 个答案:

答案 0 :(得分:27)

C ++标准保证size_t是无符号类型,无符号类型遵循通常的模运算规则(其中模数是类型值表示中位数的2,参见3.9 / 4),因此转换为-1的{​​{1}}必须是该类型可以表示的最大值。

size_t0int~0表示中的所有位都翻转为零。该结果的值取决于您平台上int的表示形式。然后将该值(可能是陷阱表示,感谢@Matt McNabb)转换为int(遵循模运算规则)。

总之,结果值是否相等是实现定义的。 (例如,如果size_t以两个补码表示,则int的值为~0,因此两者相同。)

答案 1 :(得分:19)

Assuming (guaranteed by the standard) that size_t refers to an unsigned integer value,这个:

if(pos == (size_t)~0)

意图相当于:

if(pos == (size_t)-1)

假设机器使用2's complement表示负整数。标准doesn't enforce it因此,如果您希望代码100%可移植,则不应该采用此标准。

答案 2 :(得分:1)

因此,在您的示例技术上,没有任何区别。因为很难找到不会优化-1~0等文字操作的编译器。以你的榜样,我完全得到了:

        ; ...
        movq    $-1, -16(%rbp)
        movq    $-1, -8(%rbp)
        ; ...
  

不要害怕那些-1,而且它们是无类型的;)

更有趣的问题是,如果你的例子是:

#include <stddef.h>
int main() {
        int var0 = 0;
        int var1 = 1;
        size_t a = (size_t) -var1;
        size_t b = (size_t) ~var0;
        return a ^ b;
}

在我的情况下(Kubuntu,gcc 4.8.2,x86_64,-O0选项)感兴趣的部分是:

        movl    $0, -24(%rbp)    ; var0 = 0
        movl    $1, -20(%rbp)    ; var1 = 1

        movl    -20(%rbp), %eax
        negl    %eax             ; 2's complement negation

        ; ...

        movl    -24(%rbp), %eax
        notl    %eax             ; 1's complement negation

        ; ...

查看英特尔手册:

  

NEG - 两个补语否定

     

用它替换操作数(目标操作数)的值   两个补充。 (此操作相当于   从0减去操作数。)

     

NOT - 一个补充否定

     

执行按位NOT运算(每个1设置为0,每个0   在目标操作数上设置为1)并存储   结果在目标操作数位置。

我的结论是,理论上,代码可能在某些奇特的平台和编译器上有所不同,但在其他方面 - 否则。如果不确定,请检查平台上的装配清单。