C# でバイトを OR 演算すると int [duplicate] が得られます
-
06-07-2019 - |
質問
この質問にはすでに答えがあります:
- 左ビットシフト 255 (バイトとして) 7 件の回答
このコードがあります。
byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (0x80 | dup) });
コンパイルしようとすると、次のようになります。
タイプ「int」を「バイト」に暗黙的に変換することはできません。明示的な変換が存在します(キャストがありませんか?)
なぜこのようなことが起こるのでしょうか?すべきではありません| 2つのバイトがバイトを与えますか?次のどちらも機能し、各項目がバイトであることが保証されます。
Encoding.ASCII.GetString(new byte[] { (dup) });
Encoding.ASCII.GetString(new byte[] { (0x80) });
解決
これはC#の設計による方法であり、実際、C / C ++にまでさかのぼります-後者はオペランドをint
に昇格させます。暗黙的ですが、C#ではありません。これはint -> char
だけに適用されるのではなく、すべての算術およびビット単位のオペランドにも適用されます2つの|
を追加すると、byte
も得られます。仕様の関連部分をここで引用します:
次の場合、2進数の昇格が行われます 定義済みの+、<!>#8211;のオペランド *、/、%、<!> amp;、|、^、==、!=、<!> gt;、<!> lt;、<!> gt; =、および<!> lt; =二項演算子。バイナリ 数値プロモーションは暗黙的に変換します 両方のオペランドが共通タイプになり、 非リレーショナルの場合 演算子も結果になります 操作のタイプ。 2進数 プロモーションは、 ルールに従って、順番に ここに表示されます:
いずれかのオペランドが 10進型、もう一方のオペランドは タイプdecimalに変換、または コンパイル時エラーが発生した場合 オペランドのタイプはfloatまたはdoubleです。
それ以外の場合、いずれかのオペランドが double型、もう一方のオペランドは double型に変換されます。
それ以外の場合、 いずれかのオペランドがfloat型の場合、 もう一方のオペランドは型に変換されます フロート。
それ以外の場合、いずれかのオペランド ulong型で、もう一方のオペランドは タイプulongに変換、または コンパイル時エラーが発生した場合 オペランドのタイプはsbyte、short、int、 または長い。
それ以外の場合、どちらか オペランドはlong型で、もう一方は オペランドはlong型に変換されます。
それ以外の場合、いずれかのオペランドが タイプuintおよび他のオペランドは タイプsbyte、short、またはint、両方 オペランドはlong型に変換されます。
それ以外の場合、いずれかのオペランドが タイプuint、もう一方のオペランドは uint型に変換されます。
それ以外の場合、 両方のオペランドが型に変換されます int。
これの正確な理論的根拠はわかりませんが、考えてみてください。特に算術演算子の場合、関係する型を慎重に検討すると意味があったとしても、人々が突然(byte)200 + (byte)100
に44
と等しくなるのは少し驚くかもしれません。一方、<=>は一般に<!> quot; good enough <!> quot;の型と見なされます。ほとんどの典型的な数値の算術の場合、両方の引数を<=>に昇格させると、一種の<!> quot; just works <!> quot;が得られます。最も一般的なケースの動作。
この論理がビット演算子にも適用された理由について-これは主に一貫性のためです。結果として、 all 非ブールバイナリタイプに共通の単一の単純なルールが作成されます。
しかし、これはほとんどすべて推測です。エリック・リッパーはおそらく、少なくともC#のこの決定の背後にある本当の動機について尋ねる人でしょう(ただし、答えが単に<!> quot;そのままで十分なルールなので、変更する理由はありませんでした<!> quot;)。
他のヒント
リテラル 0x80 の型は「int」であるため、バイトの論理和は計算されません。
それを byte[] に渡すことができるのは、0x80 (リテラルとして) が byte の範囲内にあるためです。
編集:0x80 がバイトにキャストされた場合でも、バイトの論理和をとると int が返されるため、コードはコンパイルされません。コンパイルするには、 or の結果をキャストする必要があります。 (byte)(0x80|dup)
byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (byte)(0x80 | dup) });
2バイトのビット単位のOr(|)の結果は常にintです。