Search notes:

VBA: Memory layout of user defined types (UDTs)

Like a C compiler (?), VBA tries to align members of a UDT on four byte boundaries.
I try to demonstrate that with the following investigations:
option explicit

type T ' {
     t_lng_1  as long
     t_byt_1  as byte
     t_byt_2  as byte
     t_lng_2  as long
     t_byt_3  as byte
     t_int_1  as integer
     t_obj_1  as object
     t_obj_2  as object
end  type ' }

type U ' {
     u_t___1  as T
     u_lng_1  as long
end type ' }

sub main() ' {

    dim tt as T

  '
  ' The following line prints 0. Thus, the address of
  ' first element in a type is the same as the
  ' address of the type-instance itself:
  '
    debug.print "t_lng_1: " & varPtr(tt.t_lng_1) - varPtr(tt        )     ' 0

  '
  ' The next element in T, t_byt_1, is four bytes apart
  ' from the first element. This is because t_lng_1
  ' occupies 4 bytes.
  '
    debug.print "t_byt_1: " & varPtr(tt.t_byt_1) - varPtr(tt.t_lng_1)     ' 4

  '
  ' The next element (t_byt_2) is also a byte. It is only
  ' one byte apart from t_byt_1, because t_byt_1 occupies
  ' one byte only.
  '
    debug.print "t_byt_2: " & varPtr(tt.t_byt_2) - varPtr(tt.t_byt_1)     ' 1

  '
  ' Interestingly, the next element (t_lng_2) is three
  ' bytes apart.
  ' This is because VBA tries to align members of type long
  ' on 4 byte boundaries:
  '
    debug.print "t_lng_2: " & varPtr(tt.t_lng_2) - varPtr(tt.t_byt_2)     ' 3

  '
  ' t_lng_2 occupies 4 bytes, hence t_byt_3 is four
  ' bytes apart:
  '
    debug.print "t_byt_3: " & varPtr(tt.t_byt_3) - varPtr(tt.t_lng_2)    '  4

  '
  ' VBA also tries to align integers on 4 byte boundaries.
  ' Hence, t_int_1 is four bytes apart from t_byt_3:w

  '
    debug.print "t_int_1: " & varPtr(tt.t_int_1) - varPtr(tt.t_byt_3)    '  2


  '
  ' The next member, an object, is aligned on a four
  ' byte boundary as well. Since t_int_1 occupies two
  ' bytes only, t_obj_1 is two bytes apart from t_int_1:
  '
    debug.print "t_obj_1: " & varPtr(tt.t_obj_1) - varPtr(tt.t_int_1)    '  2

  '
  ' An object seems to be just a pointer, thus t_obj_2 is 4 bytes
  ' apart from t_obj_1:
  '
    debug.print "t_obj_2: " & varPtr(tt.t_obj_2) - varPtr(tt.t_obj_1)    '  4

  '
  ' A TT occupies 24 bytes in memory. This is 7 times 4 bytes:
  '   - t_lng_1
  '   - t_byt_1 and t_byt_2
  '   - t_lng_2
  '   - t_byt_3
  '   - t_int_1
  '   - t_obj_1
  '   - t_obj_2
  '
    debug.print "lenB(T): " & lenB(tt)                                   ' 24

    dim uu as U

  ' debug.print varPtr(uu)

  '
  ' The following statement prints 0.
  ' Again, the address of the type-instance is the
  ' same as the address of its first element, even
  ' if this element happens to be an instance of a type.
  '
    debug.print "u_t___1: " & varPtr(uu.u_t___1 ) - varPtr(uu    )       '  0

  '
  ' The following lines prints 24. This corresponds to the
  ' size that a instance of T occupies in memory:
  '
    debug.print "u_lng_1: " & varPtr(uu.u_lng_1) - varPtr(uu.u_t___1)    ' 24

end sub ' }
Github repository about-VBA, path: /language/datatypes/user-defined/memory-layout.bas

Index