是否更容易使用~0或-1表示所有位翻转为1的类型?

时间:2017-03-18 01:44:54

标签: c++ comparison bit-manipulation

我今天看到一个代码示例,它使用以下形式检查-1是否为无符号的64位整数:

if (a == (uint64_t)~0)

是否有任何用例需要与~0进行比较而不是std::numeric_limits<uint64_t>::max()或直接-1?原来的意图对我来说并不清楚,因为我之前没有看到这样的比较。

为了澄清,比较是检查错误条件,其中无符号整数类型的所有位都设置为1

更新

根据https://stackoverflow.com/a/809341/1762276-1并不总是代表翻转到1~0的所有位。这是对的吗?

  

我建议你完全按照你所展示的那样去做,因为它是   最直接的一个。初始化为-1,它将始终有效,   独立于实际的符号表示,有时〜   有令人惊讶的行为,因为你必须有权利   操作数类型。只有这样你才能获得最高的价值   无符号类型。

我相信只要~0始终为正确的类型(如图所示),就会处理此错误情况。所以这表明(uint64_t)~0确实是一个更准确的无符号类型的门户表示,所有位都被翻转了?

以下所有情况似乎都是正确的(GCC x86_x64):

#include <iostream>
#include <limits>
using namespace std;

int main() {
    uint64_t a = 0xFFFFFFFFFFFFFFFF;

    cout << (int)(a == -1) << endl;
    cout << (int)(a == ~0) << endl;
    cout << (int)(a == (uint64_t)-1) << endl;
    cout << (int)(a == (uint64_t)~0) << endl;
    cout << (int)(a == static_cast<uint64_t>(-1)) << endl;
    cout << (int)(a == static_cast<uint64_t>(~0)) << endl;
    cout << (int)(a == std::numeric_limits<uint64_t>::max()) << endl;

    return 0;
}

结果:

1
1
1
1
1
1
1

3 个答案:

答案 0 :(得分:4)

通常,您应该在应用运算符之前进行转换,因为根据源类型是否已签名,转换为更宽的无符号类型可能会也可能不会导致符号扩展。

如果您希望设置所有位的基本类型T的值,则最便携的方法是~T(0)。它也适用于任何类似数字的类。

正如彬格莱先生所说,来自stdint.h的类型保证是两个补码,因此-T(1)也会给出一个设置了所有位的值。

您引用的来源有正确的想法,但错过了一些细节,例如(T)~0u(T)-1u都不会与~T(0u)-T(1u)相同。 (公平地说,litb并没有谈论你所链接的答案中的扩大)

请注意,如果没有变量,只有一个未填充的文字0-1,则保证源类型已签名,并且上述问题均不适用。但是,为什么在处理文字时编写不同的代码,当普遍正确的代码不再复杂时?

答案 1 :(得分:1)

std::numeric_limits<uint64_t>::max()(uint64_t)~0相同,与(uint64_t)-1

相同

查看此代码示例:

#include <iostream>
#include <stdint.h>

using namespace std;

int main()
{
    bool x = false;
    cout << x << endl;
    x = std::numeric_limits<uint64_t>::max() == (uint64_t)~0;
    cout << x << endl;
    x = false;
    cout << x << endl;
    x = std::numeric_limits<uint64_t>::max() == (uint64_t)-1;
    cout << x;
}

<强>结果:

0
1
0
1
  

所以在代码中编写(uint64_t)~0(uint64_t)-1std::numeric_limits<uint64_t>::max()更简单。

答案 2 :(得分:1)

uint64_t这样的固定宽度整数类型是guaranteed,以二进制补码表示,因此对于那些-1~0是等价的。对于普通的整数类型(如intlong),情况不一定如此,因为C ++标准没有指定它们的位表示。