2016-09-15 10 views
2

私は以前のプログラマを編集していたコードでは、shift演算子を使ってsize_tの整数に適度に大きな数を加えました。デバッグの目的でこの特定の整数で試合をしたときに、数値を変更しても予測可能な結果が得られないことがわかりました。シフト演算子(C++)でランダムな結果が得られるのはなぜですか?

入力:

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は理論的に可能な任意のタイプ(配列を含む)のオブジェクトの最大サイズを格納できます。それでは、整数が宣言されているかビットシフトがどのように動作しているかの問題があると思います。

何が起こっているのですか?

+0

'size_t'は「事実上無制限」ではありません。任意のオブジェクトのサイズ*をバイト数で示すのに十分な大きさであることが保証されています。実際には、[cppreferenceでサンプルコードをコンパイルするために使用される実装は、最大値が '18446744073709551615'(http://en.cppreference.com/w/cpp/types/numeric_limits/max#Example)ですが、これは実際には必要最低限​​よりもはるかに大きい。 –

答えて

11

問題はstd::size_tではなく、intリテラルが使用されています。

#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 

Live Demo


はまた、コンパイラがそのことについて正確にあなたに警告を与える注意:

あなたは、彼らが十分な長さ、ここのような UL接尾辞を使用して行うことができます
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; 
      ~~~~~~~^~~~~ 
関連する問題