2012-01-03 21 views
7

私は説明が見つからない左シフトの結果を得ています。なぜunsigned char << unsigned charの結果がunsigned charではない

unsigned char value = 0xff; // 1111 1111 
unsigned char = 0x01; // 0000 0001 

std::cout << "SIZEOF value " << sizeof(value) << "\n"; // prints 1 as expected 
std::cout << "SIZEOF shift " << sizeof(shift) << "\n"; // prints 1 as expected 

std::cout << "result " << (value << shift) << "\n"; // prints 510 ??? 

std::cout << "SIZEOF result " << sizeof(value << shift) << "\n"; // prints 4 ??? 

私は1111 1110する結果を期待していたが、代わりに、私はintを取得する(?)1 1111 1110の値を持ちます。

符号なしcharのビットを左にシフトすると、ビットが切り捨てられ、結果は1111 1110になりますか?

私がしようとしているのは、一連のバイトを読み取って、さまざまな長さ(1〜32ビット)の整数として解釈することです。

F0  F5 
1111 0000 1111 0101 

0F (first 4 bits) 
0F (next 8 bits) 
05 (last 4 bits) 

は算術がintよりも小さいタイプで行われていないという事実を行うには、この何かを持っているだろうか?

+0

11111111 << 1は実際には111111110なので、式の結果を表示しています: 'value = value << shift;'そして 'cout << value;' – Yaniro

答えて

9

5.8 Shiftキーを演算子[expr.shift]

...

オペランドは、整数型またはスコープなしの列挙型で、積分型昇格が実行されます。 結果のタイプは、昇格された左オペランドのタイプです。 【conv.prom]

その整数変換 ランク(4.13)BOOL、char16_t、char32_t、またはwchar_t型以外の整数型のprvalueある

4.5インテグラプロモーションintのランクより小さい値はint型のprvalueに変換することができます。intはすべてソースタイプの値を で表すことができます。それ以外の場合は、ソースprvalueは

ので、valueintに昇格さ... int型

unsigned型のprvalueに変換され、value << shiftの種類は昇格左オペランドのタイプであることができますすなわち、int

あなたはあなたの目的の結果次のいずれかの方法を達成することができます:あなたが興味を持っているビットマスクができ

std::cout << "result " << ((unsigned char)(value << shift)) << "\n"; 
std::cout << "result " << ((value << shift)&0xff) << "\n"; 
2

戻ったばかりのunsigned char型にキャスト:

std::cout << "result " << static_cast<unsigned char>(value << shift) << "\n"; 

または、ビットごとのANDを使用します。

2011標準のいくつかの案引用
std::cout << "result " << ((value << shift) & 0xFF) << "\n"; 
2

を:あなたが見ている何

(value << shift) & 0xff 

を整数プロモーションの結果であります、言語の一部です。 2つの8ビット整数から16ビットの整数を構成しているとします。上位ビットと下位ビットを適切な場所に手動で昇格させたくないでしょうか?

関連する問題