为什么我得到随机结果与移位操作符(c++)

Why am I getting random results with the Shift Operator (C++)?

本文关键字:操作符 位操作 c++ 随机 结果 为什么      更新时间:2023-10-16

在我一直在编辑的代码中,前面的程序员使用移位运算符向size_t整数添加一个中等大小的数字。当我为了调试而使用这个特定的整数时,我发现改变这个数字并不能产生可预测的结果。

输入:

std::size_t
    foo1 = 100000 << 20,
    foo2 = 200000 << 20,
    foo3 = 300000 << 20,
    foo4 = 400000 << 20;
std::cout << "foos1-4:";
std::cout << foo1;
std::cout << foo2;
std::cout << foo3;
std::cout << foo4;

收益率:

foos1-4:
1778384896
18446744072971354112
1040187392
18446744072233156608

我知道这是某种溢出错误,但是(据我所知有限)size_t不应该有这些错误。根据我的理解,size_t是一种无符号整数类型,它能够容纳几乎无限数量的整数。

根据我对位移位运算符的理解,这段代码应该将数字乘以2^20(1048576)。连结至本网站其他网页:什么是按位移位(bit-shift)运算符,它们是如何工作的?

注意-我手工计算出foo1似乎是一个32位二进制截断的溢出错误,但所有其他的对我来说似乎完全随机。

从http://en.cppreference.com/w/cpp/types/size_t

:size_t可以存储任何类型(包括数组)的理论上可能的对象的最大大小。由此,我认为问题一定在于如何声明整数或如何操作位移位。

怎么回事?

问题不在于std::size_t,而在于所使用的int字面量。您可以使用UL后缀使它们足够长,如下所示:

#include <iostream>
int main()
{
std::size_t
    foo1 = 100000UL << 20,
    foo2 = 200000UL << 20,
    foo3 = 300000UL << 20,
    foo4 = 400000UL << 20;
std::cout << "foos1-4:" << std::endl;
std::cout << foo1 << std::endl;
std::cout << foo2 << std::endl;
std::cout << foo3 << std::endl;
std::cout << foo4 << std::endl;
}
输出:

foos1-4:
104857600000
209715200000
314572800000
419430400000

现场演示


还需要注意的是,编译器会给你一个警告:

main.cpp:6:19: warning: result of '(100000 << 20)' requires 38 bits to represent, but 'int' only has 32 bits [-Wshift-overflow=]
     foo1 = 100000 << 20,
            ~~~~~~~^~~~~
main.cpp:7:19: warning: result of '(200000 << 20)' requires 39 bits to represent, but 'int' only has 32 bits [-Wshift-overflow=]
     foo2 = 200000 << 20,
            ~~~~~~~^~~~~
main.cpp:8:19: warning: result of '(300000 << 20)' requires 40 bits to represent, but 'int' only has 32 bits [-Wshift-overflow=]
     foo3 = 300000 << 20,
            ~~~~~~~^~~~~
main.cpp:9:19: warning: result of '(400000 << 20)' requires 40 bits to represent, but 'int' only has 32 bits [-Wshift-overflow=]
     foo4 = 400000 << 20;
            ~~~~~~~^~~~~