A simple query about Left Shift (<<)

Dim A As Byte() = New Byte() {231, 3}
Call Test(A, 0)

Private Function Test(ByVal Array As Byte(), ByVal StartAddress As Integer) As Integer

Dim A As Integer = Array(StartAddress + 1) << 8
Dim b As Integer = A << 8
Dim c As Integer = 231
Dim d As Integer = A Or c
Stop

End Function

When the function Stops, the variables equal the following:
A = 3
b = 768
c = 231
d = 231

3 << 8 = 768, but Array(StartAddress + 1) << 8 does not equal 768. Even though Array(StartAddress + 1) = 3.

Why is this

Also, is there anyway to view the code for System.Bitconverter to see how it's done

Thank you,
Troy L




Answer this question

A simple query about Left Shift (<<)

  • bluedvd

    Thank you for your reply. Especially because you explained your reasoning. I got it to work nonetheless.

    Private Function Read32(ByVal Array As Byte(), ByVal Index As Integer) As Long
    Dim A As Long = CLng(Array(Index + 3)) << 24
    Dim B As Long = CLng(Array(Index + 2)) << 16
    Dim C As Long = CLng(Array(Index + 1)) << 8
    Dim D As Long = Array(Index)

    Return A Or B Or C Or D
    End Function

    Also, do you know what the how to look at the code for system.bitconverter I want to see how it is accomplished through that method.
    Thanks,
    Troy L.



  • project2n5e0o1

    I have another question that may or may not be related.

    I use Dim A as Integer = 222 << 24
    This give me the answer -570425344

    When I do this in calculator i get 3724541952

    I am trying to make my own function to read 32bits. Here it is:

    Private Function Read32(ByVal Array As Byte(), ByVal Index As Integer) As Integer
    Dim A As Integer = (0 Or Array(Index + 3)) << 24
    Dim B As Integer = (0 Or Array(Index + 2)) << 16
    Dim C As Integer = (0 Or Array(Index + 1)) << 8
    Dim D As Integer = Array(Index)

    Return A Or B Or C Or D
    End Function

    Any ideas

    Troy L.



  • Crane101

    I'm not sure how to look at the code for System.BitConverter, because it is unmanaged. If you somehow found a way to look at the code, it will appear in Assembler and not VB.NET. I believe the unmanaged code itself is located in C:\windows\microsoft.net\Framework\v2.0.50727\mscorlib.dll. If you open this file with ILdasm, supplied with the .NET SDK, most of the methods in System.BitConverter will be empty (again, because they are unmanaged). However, you will be able to view some of the methods.

    I think the best way to accomplish this method in managed code is to use Integer or UInteger instead of Long - you will experience a slight slowdown using Long on 32-bit processors.

    maybe someone else can chime in on the benefit of using Long vs. Integer here. I'm not sure which is better when you consider that 64-bit CPU's are becoming more commonplace.


  • Joe Dawson

    This is because for the Integer datatype, the highest bit is the sign bit. When you do this:

    222 << 24

    Keep in mind that 222, in binary, has its highest bit ON. So when you L-shift by 24 and put it in an integer, the Integer's highest bit will be ON, so it is negative.

    In most cases, having the negative number -570425344 instead of 3724541952 is not even wrong per se; the bit representation for either number is the same, and when you are working in bitwise logic and math, how the number appears is usually not important.

    In any case, if you want the value to look correct, change Integer to UInteger, so that the highest bit is not the sign bit:

    Private Function Read32(ByVal Array As Byte(), ByVal Index As Integer) As UInteger
    Dim A As UInteger = CUInt(0 Or Array(Index + 3)) << 24
    Dim B As UInteger = (0 Or Array(Index + 2)) << 16
    Dim C As UInteger = (0 Or Array(Index + 1)) << 8
    Dim D As UInteger = Array(Index)

    Return A Or B Or C Or D
    End Function


  • Alex.Zealot

    The reason is because you are shifting too many bits for the data type. Bytes have 8 bits each, so bit-shifting by anything more than 8-bits will give you something you don't want. This is the right way to shift so many bits:

    Dim A As Byte() = New Byte() {231, 3}
    Call Test(A, 0)

    Private Function Test(ByVal Array As Byte(), ByVal StartAddress As Integer) As Integer

    Dim A As Integer = CInt(Array(StartAddress + 1)) << 8
    Dim b As Integer = A << 8
    Dim c As Integer = 231
    Dim d As Integer = A Or c
    Stop

    End Function

    Note the CInt() conversion. Integers have 32 bits, so they have enough room.

    The reason 3 << 8 = 3, is because your system is Modding the "8" by 8 (which is the capacity of Bytes) before it performs the operation. So to rewrite the expression as your CPU is executing it:

    3 << 0 = 3

    - which actually makes sense. I'm not sure if this behavior is guaranteed by .NET, or if it varies by CPU though.


  • A simple query about Left Shift (<<)