1

私は C# に移行しようとしている Java プログラマーですが、この落とし穴には少し困惑しています。

int a = 1;

a = 0x08000000 | a;
a = 0x80000000 | a;

最初の行は問題なくコンパイルされます。2番目はそうではありません。符号ビットを持つ定数があることを認識しているようで、何らかの理由で結果を long にキャストすることを決定し、エラーが発生します。

タイプ 'long' を 'int' に暗黙的に変換することはできません。
明示的な変換が存在します (キャストがありませんか?)

これまでの修正は次のとおりです。

a = (int)(0x80000000 | a);

キャストを処理しますが、それでも警告が残ります:

符号拡張オペランドで使用されるビットごとの OR 演算子。
最初に小さい符号なし型にキャストすることを検討してください

これをエラー/警告/ロングフリーの方法で表現する正しい C# の方法は何でしょうか?

4

6 に答える 6

12

これらすべての回答の中で、警告の内容を実際に提案したのは1人だけだったのは興味深いことです。警告は、問題を修正する方法を示しています。それに注意を払ってください。

ビット単位-または符号拡張オペランドで使用される演算子。最初に、より小さな符号なしタイプにキャストすることを検討してください

ビット単位または演算子は、符号拡張オペランドであるintで使用されています。そのため、結果はより大きなタイプ(long)に変換されます。longよりも小さいunsignedタイプはuintです。したがって、警告の内容を実行してください。符号拡張オペランド--int--をuin​​tにキャストします。

result = (int)(0x80000000 | (uint) operand);

現在、符号拡張はありません。

もちろん、これはより大きな問題を提起するだけです。そもそもなぜ符号付き整数をビットフィールドとして扱っているのですか?これは危険なことのようです。

于 2010-01-15T15:43:07.407 に答える
12

数値整数リテラルは、数値intが大きすぎて に収まらず、代わりにintになる場合を除いて、デフォルトで です (およびについても同様です)。uintlongulong

値 0x80000000 は大きすぎて に収まらないためintuint値です。anおよび an both|で演算子を使用すると、どちらも安全に他方に変換できないため、両方が拡張されます。intuintlong

値は int として表現できますが、負の値になることを無視する必要があります。コンパイラはそれを暗黙のうちに実行しないためint、オーバーフローを気にせずに値を an にするように指示する必要があります。

a = unchecked((int)0x80000000) | a;

(注: これは、値を変換する方法をコンパイラに指示するだけなので、への変換を行うためのコードは作成されませんint。)

于 2010-01-15T14:18:55.057 に答える
1

問題は、0x80000000がint形式のマイナスであり、マイナス値に対してビット単位の演算を実行できないためです。

uintを使用すると、正常に動作するはずです。

a = ((uint)0x80000000) | a;  //assuming a is a uint
于 2010-01-15T14:09:59.330 に答える
1

その行をに変更する
(int)((uint)0x80000000 | (uint)a);
と、私のためにそれを行います。

于 2010-01-15T14:15:47.360 に答える
0

文字「O」で始まる定数を作成することで、見苦しさを軽減できます。(この Web サイトとは異なり、Visual Studio では別の色で表示されません)。

const int Ox80000000 = unchecked((int)0x80000000);

/// ...

const int every /*  */ = Ox80000000;
const int thing /*  */ = 0x40000000;
const int lines /*  */ = 0x20000000;
const int up /*     */ = 0x10000000;
于 2012-07-30T02:20:02.990 に答える
0

ここであなたが抱えている問題は、

  • 0x80000000符号なし整数リテラルです。仕様では、整数リテラルは、リテラルを保持できるリスト ( intuintlongulong) の最初の型であると述べています。この場合は ですuint
  • aおそらく_ _int

これにより、結果long. int結果をにキャストする以外に良い方法はありaません。a次に、最初にそのようにキャストuintまたは宣言できます。

于 2010-01-15T14:21:32.323 に答える