Побитовый сдвиг против Умножения - PullRequest
0 голосов
/ 25 июня 2018

Я часто использую побитовые операторы в своей работе и пишу в VB.NET. Когда создается переменная типа System.Byte, требуется приведение типа для сдвига байта влево:

Dim a As Byte = &HFF
Dim b As Integer = a * 256
Debug.WriteLine(b.ToString("X")) 
Dim c As Integer = a << 8 'without cast'
Debug.WriteLine(c.ToString("X"))
Dim d As Integer = CInt(a) << 8 'with cast'
Debug.WriteLine(d.ToString("X"))

Вывод:

FF00

FF

FF00

Использование «* 256» позволяет пропустить приведение типов, и код выглядит короче, особенно если используется несколько сдвигов в одном выражении. Но в отличие от смены такая запись не выглядит ясной.

Итак, вопрос в том, какой тип предпочтительно в одном и том же случае? Умножение занимает больше процессорного времени или нет?

1 Ответ

0 голосов
/ 26 июня 2018

Я загрузил этот VB-код в декомпилятор ILSpy, и это было показано:

IL_0001: ldc.i4 255
IL_0006: stloc.0

// 255 * 256
IL_0007: ldloc.0
IL_0008: ldc.i4 256
IL_000d: mul.ovf
IL_000e: stloc.1 //equal part starts
IL_000f: ldloca.s 1
IL_0011: ldstr "X"
IL_0016: call instance string [mscorlib]System.Int32::ToString(string)
IL_001b: call void [System]System.Diagnostics.Debug::WriteLine(string)

// 255 << 8
IL_0021: ldloc.0
IL_0022: ldc.i4.8
IL_0023: ldc.i4.7
IL_0024: and
IL_0025: shl
IL_0026: conv.u1
IL_0027: stloc.2 //equal part starts
IL_0028: ldloca.s 2
IL_002a: ldstr "X"
IL_002f: call instance string [mscorlib]System.Int32::ToString(string)
IL_0034: call void [System]System.Diagnostics.Debug::WriteLine(string)

// cint(255) << 8
IL_003a: ldloc.0
IL_003b: ldc.i4.8
IL_003c: shl
IL_003d: stloc.3 //equal part starts
IL_003e: ldloca.s 3
IL_0040: ldstr "X"
IL_0045: call instance string [mscorlib]System.Int32::ToString(string)
IL_004a: call void [System]System.Diagnostics.Debug::WriteLine(string)

Как видите, 5 последних строк IL-кода равны для каждой инструкции высокого уровня.Разница только в верхней части каждой части.И 0xFF * 256 содержит только 3 оператора, CInt (0xFF) << 8 </strong> содержит 3 оператора, а 0xFF << 8 </strong> содержит 6 операторов, т.е. еще 2раз!Битовое смещение без приведения типов использует битовую маску для предотвращения возможного переполнения, что добавляет дополнительные операторы в код IL.

Кроме того, я обнаружил в книге Франческо Балены «Программирование Microsoft Visual Basic 2005: язык», что побитовое смещение быстрее для типов Long и ULong.Для типов Integer и Short битовое смещение равно умножению.

Итак, мой вывод:

  • для битового сдвига Long и ULong быстрее умножения;

  • для всех других типов(с приведением типа к результату битности) умножение происходит быстрее или равно битовому сдвигу, поэтому использование первого или второго регистра - только вкус разработчика.

...