为什么我使用移位运算符 (C++) 得到随机结果?
Why am I getting random results with the Shift Operator (C++)?
在我编辑的代码中,以前的程序员使用移位运算符将一个中等大的数字加到 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)。本网站其他页面的链接:
What are bitwise shift (bit-shift) operators and how do they work?
注意 - 我手工计算出 foo1 似乎是一个溢出错误,带有 32 位二进制数字截断,但所有其他对我来说似乎完全是随机的。
来自http://en.cppreference.com/w/cpp/types/size_t:
std::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;
~~~~~~~^~~~~
在我编辑的代码中,以前的程序员使用移位运算符将一个中等大的数字加到 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)。本网站其他页面的链接: What are bitwise shift (bit-shift) operators and how do they work?
注意 - 我手工计算出 foo1 似乎是一个溢出错误,带有 32 位二进制数字截断,但所有其他对我来说似乎完全是随机的。
来自http://en.cppreference.com/w/cpp/types/size_t: std::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;
~~~~~~~^~~~~