Members

Technology Zones

IBM Learning Center

Articles

Hosted By

MaximumASP

Info

Rated
Read 49,973 times

Contents

Downloads

Related Categories

CopyMemory and Arrays: Proper Use - The Tricky Part

webjose

The Tricky Part

I mentioned that the calculation of the number of bytes to be moved was tricky. Well, it is because Visual Basic will pad certain UDT's with non-used bytes. But what does this mean? I'll detail this with an example.

Look at the following UDT:

Private Type TestType
    var1 As Long
    var2 As Integer
    var3 As Single
End Type

TestType seems to occupy 10 bytes: 4 bytes for the long (var1), 2 bytes for the integer (var2), and 4 bytes for the single number (var3). However, if you run the following code snippet you will prove this is not correct.

Public Sub Main()

Dim myVar As TestType

    MsgBox "LenB(myVar) = " & CStr(LenB(myVar)), vbInformation
End Sub

The message box will read "LenB(myVar) = 12". This can only mean one thing: Visual Basic will align the second variable in memory so it occupies 4 bytes instead of 2. This is normally referred to as DWORD alignment.

NOTE: DWORD stands for "double word", and it is a term that comes from the old computing days. A Word is two bytes, a DWORD is four bytes, and now with the introduction of 64-bit machines, a QWORD (quad word) is 8 bytes. Windows programming in C++ have maintained this nomenclature.

If you like, you can mess with the order of the variables in TestType. If you do, you will notice that if the integer goes down to the last position like in the following UDT, LenB() will return the original expected result: 10. A new piece of information for the resolution of this puzzle: A 2-byte variable will not be DWORD-aligned if it is at the end of the UDT.

Private Type TestType
    var1 As Long
    var3 As Single
    var2 As Integer
End Type

Now let's try with one-byte variables. Run the previous test with this UDT declaration:

Private Type TestType
    var1 As Long
    var2 As Byte
    var3 As Single
End Type

The result is 12 bytes again. But what about this next one?

Private Type TestType
    var1 As Long
    var3 As Single
    var2 As Byte
End Type

The result is 9 bytes, the result we could have obtained by manually adding up the bytes for each data type. Now the puzzle is almost complete. Let us see what happens with a more complex UDT:

Private Type TestType
    var1 As Long
    var2 As Byte
    var4 As Byte
    var3 As Single
End Type

This one returns 12 too. The following also yields 12.

Private Type TestType
    var1 As Long
    var2 As Integer
    var4 As Integer
    var3 As Single
End Type

Summarizing...

What can we say about these tests? Well, we can say that all variables not occupying a multiple of 4 bytes in the middle of a UDT declaration (the order of declaration determines the order they are stored in memory) will get padded so they are DWORD-aligned.

And to wrap this result up with CopyMemory, I must say that the number of bytes is of PARAMOUNT importance because you will not get the correct results if you do not use the correct number of bytes. This could happen if you confuse LenB() with Len(), or if you hardcode the number of bytes occupied by a UDT.

To finally complete the discussion on CopyMemory and UDTs and arrays, I must note a few restrictions of use. Please read the next page of this article.

This code is for everyone's use and, although I have tested it the best I can, I cannot be held responsible for its use or misuse, or for any other type of damage WHATSOEVER. Use this code at your own risk. If you find an error or can improve it, feel

Comments

  • ReDimm statement is innefficient

    Posted by kwadrofonik on 26 Jun 2004

    Thanks. Definately some good information, however...

    It is not very practical to use the ReDim statement each iteration of a loop since it copies the entire array to a different memory location in ...

  • Interesting case

    Posted by webjose on 01 Mar 2003

    I just tested and yes, you are correct.

    Private Type MyType
    var1 As Integer
    var2 As Byte
    var3 As Boolean
    End Type

    The above type will get padded to a WORD, not a DWORD. However,...

  • DWORD padding.

    Posted by BitShifter on 01 Mar 2003

    I'm willing to bet that if he first variable in the UDT had been an integer, the following Bytes would have been padded to WORD size and no more.

    This being the start of the week-end, I'll play wit...