C # Побитовый или оператор, используемый в операнде с расширенным знаком; сначала рассмотрите приведение к меньшему типу без знака - PullRequest
19 голосов
/ 07 сентября 2011

Я знаю, что эти предупреждения, вероятно, бессмысленны.

Я получил 7 из этих предупреждений.

Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first

Это как-то связано с оператором ИЛИ |

Я выделил то, что испускает предупреждения.

int result = (int)ror((uint)(v76 ^ (v75 | 0x862D63D3)), (uint)(BitConverter.ToInt32(v4, 72) ^ 0x22));

int v11 = (int)rol((uint)(int)((v8 & v10 | ~v10 & 0xEFCDAAC9) + v3[2] - 1126481991), 17);

int v144 = (int)rol((uint)(int)((v141 & v143 | ~v143 & 0xEFCDAAC9) + v3[2] - 1126481991), 17);

int v77 = (int)(`BitConverter.ToInt32(v4, 52) | 0x96C35837`);


BitConverter.GetBytes((int)(v30 & 0x870DEA8A | v29)).CopyTo(v2, 32);

int temp24 |= (int)(BitConverter.ToInt32(v3, 48) | 0x96B4A1B4);

int v17 = (int)(BitConverter.ToInt32(v3, 12) | 0x83868A1D);

Ответы [ 3 ]

25 голосов
/ 07 сентября 2011

Быстрый веб-поиск показывает официальную документацию для предупреждения , которая поставляется с объяснением:

Компилятор неявно расширяет и расширяет знак переменной, а затем использовал полученное значение в побитовой операции ИЛИ. Это может привести к неожиданное поведение.

Проблема в том, что выражение v75 | 0x862D63D3 имеет форму int | uint. Это вычисляется путем продвижения обеих сторон к long. Если вы действительно хотите расширение знака, напишите (ulong)(long)v75 | 0x862D63D3. Если вы действительно хотите нулевое расширение, напишите (uint)v75 |0x862D63D3.

class Program {
 public static void Main()
 {
  int v75 = int.MinValue;
  System.Console.WriteLine("{0:x}", v75 | 0x862D63D3);
  System.Console.WriteLine("{0:x}", (ulong)(long)v75 | 0x862D63D3);
  System.Console.WriteLine("{0:x}", (uint)v75 | 0x862D63D3);
 }
}

Эта программа печатает

ffffffff862d63d3
ffffffff862d63d3
862d63d3

Как видите, компилятор по умолчанию использует первую интерпретацию, что, вероятно, не то, что вам нужно.

2 голосов
/ 07 сентября 2011

Попробуйте привести v75 и другие переменные, имеющие ORed, к шестнадцатеричным значениям без знака:

((uint)v75 | 0x862D63D3)

или объявите переменные как uint вместо int.

1 голос
/ 20 апреля 2016

если вы выполняете операцию ИЛИ для int и long, то система приводит int к long. Существуют два пути для этого:

namespace ConsoleApplication1
{
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine($"int.MinValue  = {Convert.ToString(int.MinValue, 2)}");
        Console.WriteLine($"long.MinValue = {Convert.ToString(long.MinValue, 2)}");

        Console.WriteLine();

        long cast1 = int.MinValue;                   // !!!
        long cast2 = unchecked((uint)int.MinValue);  // !!!

        Console.WriteLine($"default cast = {Convert.ToString(cast1, 2)}");
        Console.WriteLine($"custom  cast = {Convert.ToString(cast2, 2)}");

        Console.WriteLine();

        Console.WriteLine($"default long OR int = {Convert.ToString(long.MinValue | int.MinValue, 2)}");
        Console.WriteLine($"custom  long OR int = {Convert.ToString(long.MinValue | unchecked((uint)int.MinValue), 2)}");
}
}

Результат:

int.MinValue  = 10000000000000000000000000000000
long.MinValue = 1000000000000000000000000000000000000000000000000000000000000000

default cast = 1111111111111111111111111111111110000000000000000000000000000000
custom  cast = 0000000000000000000000000000000010000000000000000000000000000000

default long OR int = 1111111111111111111111111111111110000000000000000000000000000000
custom  long OR int = 1000000000000000000000000000000010000000000000000000000000000000

Как результат вы хотите?

...