Library tutorials & articles

CopyMemory and Arrays: Proper Use

Fundamentals

What is an Array?

A basic definition of an array would be: A collection of items of the same type, where each item has assigned a index number. Sounds simple enough, but in order to take advantage of it, we must get past this definition and enter the dark side of it: How arrays are stored in memory.

A Little Foreplay Is Always Necessary, As They Say

For me to successfully explain this concept, I must mention a little something about RAM, or the computer memory. RAM is linear. This means it is not layed out in some complex two or three-dimensional or n-dimensional form or something of that sort. It is very simple: The first byte is followed by the second byte, which is also followed by the third byte, and so on. All the bytes available in RAM are one next to the other. No special directions to reach a particular byte are needed. You just say byte 0, byte 1, byte 65536 (the first byte after the first 64Kb of memory). All you have to do is count from the first byte to the byte number given.

The numbers I just presented above are to be considered memory pointers. If you have a variable pointing to byte 65536 and the data stored there is a long value (4 bytes), then the next available RAM space is at byte 65536 + 4 = 65540 (plus four because a long value requires 4 bytes). Normally, you will see pointer values written in hexadecimal format. It is the same thing, but Hex is preferred because of its compact mode, among other few advantages.

Working with pointers is somewhat simple, but not so simple for VB programmers. You see, math for pointers require that the pointer variables do not reserve the most significant bit for the sign, and that variables holding pointers must be 4 bytes long. Why this? Simple really: There are no negative byte counts. You never refer to a byte as byte -30; there is just no such thing. This is why you should always be very careful when using a pointer to get another pointer by adding an offset of bytes. As a general rule of thumb, you should never do this calculation except for positive pointers while working in VB.

After explaining the layout of RAM, we can now move on to our next, more to the point, topic: UDT's and arrays. They are, in essence, the same thing: A collection of values. Example:

Type MyType
    var1 as Long
    var2 as Integer
    var3 as Boolean
End Type

Private tMyType As MyType
Private arrMyArray(1 to 10) As Long

Both tMyType and arrMyArray are a collection: The first one is a collection of three values: A Long, a Integer, and a Boolean value; the second one is a collection of 10 Long values. Well, now you might be wondering why I mentioned this. The reason is very important: Both "collections" store all their values in consecutive bytes in RAM. This means that, in the case of tMyType, the Long value preceeds the Integer value, which in turn preceeds the boolean value. In the case of the array arrMyArray above, array element 1 preceeds element 2, etc.

And why is this important? It is important because this permits the use of CopyMemory to copy several values at once to a different location, which is what I will explain very shortly.

Comments

  1. 26 Jun 2004 at 07:49

    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 order to change the dimension. In fact, using the CopyMemory function for this purpose is useful as well. A good compromise would be to redimension the array every 20th iteration and then check for empty array values, such as:


    If SubDirCount = UBound(DirList) Then ReDim Preserve DirList(UBound(DirList) + 20)


    an even better solution is to use an array object.

  2. 01 Mar 2003 at 13:25

    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, starting with a WORD is not enough.  The following will get DWORD-aligned, meaning you must not have DWORDS or QWORDS.


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


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


    Private Type MyType
       var1 As Integer
       var3 As Double
    End Type


    Thanks for the observation.  I will update the article to add the finding.

  3. 01 Mar 2003 at 11:03

    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 with this later...

  4. 01 Jan 1999 at 00:00

    This thread is for discussions of CopyMemory and Arrays: Proper Use.

Leave a comment

Sign in or Join us (it's free).

Jose Pablo Ramirez Vargas
AddThis

Related discussion

Related podcasts

  • Christian Beauclair

    14 mai 2008 (�mission #0074) ::.Christian Beauclair: Stratégies de migration VB6 vers .NET Nous discutons avec Christian Beauclair des stratégies de migration VB6 vers .NET. Entre autres, nous discutons comment utiliser le "VB 6 Code Advisor" et le "Interop Forms Toolkit" pour ajouter la puiss...

We'd love to hear what you think! Submit ideas or give us feedback