无符号长整型无法存储超过 2,147,483,647 的正确数字。

4

源代码:

#include <iostream>
using namespace std;
int main() {
        unsigned long P;

        P = 0x7F << 24;
        cout << P << endl;

        P = 0x80 << 24;
        cout << P << endl;

        return 0;
}

输出:

2130706432
18446744071562067968

正如您所看到的,第一个结果是正确的。 但第二个结果极其错误。 期望的结果是2147483648,而它与18446744071562067968不匹配。

我想知道为什么。


2
0x80ul << 24 - Marek R
2
假设使用32位int的实现,0x80的类型为int,左移后的结果也是int类型。它不是无符号的。因此,0x80 << 24会导致int溢出,从而产生未定义的行为。 - Peter
2个回答

10

表达式0x80 << 24的类型不是unsigned long,而是int。之后您将该表达式的结果分配给P,并在此过程中将其转换为unsigned long。但此时它已经溢出(附带导致未定义的行为)。请在表达式中使用unsigned long文字:

P = 0x80ul << 24;

4

这个问题并非完全可移植,因为它取决于您对无符号长整型(unsigned long)表示中的位数。在这种情况下,会发生溢出和下溢,两种效应相结合产生了令人惊讶的结果。

基本解决方案在此处指定:数字文字中使用ULL后缀

我已在下面的代码中进行了分解。


#include <iostream>
using namespace std;
int main() {

        cout << "sizeof(unsigned long) = " << sizeof(unsigned long) << "\n";
        cout << "sizeof(0x80) = " << sizeof(0x80) << "\n";

        int32_t a = (0x80 << 24); // overflow: positive to negative
        uint64_t b = a; // underflow: negative to positive

        uint64_t c = (0x80 << 24); // simple broken
        uint64_t d = (0x80UL << 24); // simple fixed
        uint32_t e = (0x80U << 24); // what you probably intended

        cout << "a = " << a << "\n";
        cout << "b = " << b << "\n";
        cout << "c = " << c << "\n";
        cout << "d = " << d << "\n";
        cout << "e = " << e << "\n";

}

输出:

$ ./c-unsigned-long-cannot-hold-the-correct-number-over-2-147-483-647.cpp 
sizeof(unsigned long) = 8
sizeof(0x80) = 4
a = -2147483648
b = 18446744071562067968
c = 18446744071562067968
d = 2147483648
e = 2147483648

如果你正在进行位移操作,像这样的话,最好明确整数的大小(正如我在上面的代码中所展示的)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接