我经常在工作中使用按位运算符并在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”允许跳过类型转换,并且代码看起来更短,特别是如果在一个表达式中使用很少移位的情况下。但是这种记录不像shift那样清晰。
那么问题是在相同情况下最好是哪种类型?乘法是否需要更多的处理器时间?
答案 0 :(得分:0)
我已将此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)
如您所见,每个高级指令的IL代码的最后5个字符串相等。差异仅在于每个部分的顶部。并且 0xFF * 256 仅包含3个运算符, CInt(0xFF)<< 8 包含3个运算符,而 0xFF << 8 包含6个运算符,即再2次!没有类型转换的按位移位使用位掩码来拒绝可能的溢出,这会将附加的运算符附加到IL代码中。
此外,我在Francesco Balena的《编程Microsoft Visual Basic 2005:该语言》一书中发现,对于Long和ULong类型,按位移位更快。对于Integer和Short类型,按位移位等于乘法。
所以我的结论是:
Long和ULong的按位移位比乘法快;
对于所有其他类型(类型转换为结果位数),乘法运算更快或等于按位移位,因此使用第一种或第二种情况仅是开发人员的喜好。