Variables, Values, and Arrays in VBScript (Part 2 of a 3-Part Series), Part 2By Bill Wilkinson
In Part 1 we examined how VBScript internally handles single-dimension arrays. In this part we'll look at VBScript's treatment of multi-dimensional arrays!
Actually, that title is a little bit of a fib. We aren't going to discuss anything but two-dimensional arrays, for space and time reasons. But, really, extending the concepts on to more than two dimensions is not hard - it's just tedious. So...
The question: How are two-dimensional arrays represented in memory?
The answer: The same as single dimensional arrays. Except that the "rows" are themselves contiguous.
To illustrate, let's say you do:
Then in memory you would find all the elements, contiguously, in this order:
ar(0,0) ar(1,0) ar(0,1) ar(1,1) ar(0,2) ar(1,2) ar(0,3) ar(1,3)
So to find element
ar(x,y), you first find the address of
and then treat the
y row as a sub-array and find the address of element
x within it.
And that sounds complicated, but it's really easier than it sounds. The math looks like this:
Let's look at that a piece at a time:
That's how many elements there are in each row. For our array
UBound(ar,1) is 1, yes? So one more than that is 2. Indeed, there are two
elements in each row. Then we multiply that by 16:
and that gets us how many bytes there are in each row (because, of course, every element
is a VARIANT and every element thus occupies 16 bytes). [In this case, each row occupies 32
2 * 16.] We find the address of the beginning of the
by multiplying by
Then we have to find the location of element
x in that row (or subarray, as we
called it above). So to all of that we simply add:
And, finally, we add on the address of the start of the array and thus get the address of
Now...Why does VBScript choose this particular scheme? For example, why is the row number
the second dimension of the array, instead of the first as is common in many other languages?
Simply so that
ReDim Preserve is easier to implement!
Suppose you start with that array, above, and then do
What does the language have to do?
First, it allocates enough memory for the new array:
16 * 2 * 6 bytes (192 bytes).
Then it simply copies the old array, starting at its starting address and for the size of the
old array to the starting address of the new array. Presto! It is done! (Well, the elements of
the new array beyond the end of the old have to get zeroed out, but that's a detail.)
If it did the memory layout any other way,
ReDim Preserve would be a lot more
work! And note that, because of the way VARIANTs work universally, none of the elements in
the newly sized array need to be touched, at all! Primitive values (numbers, etc.) are of
course still fine. And pointers to objects (including strings) are still...well...pointing to
the right place!
Incidentally, if you care, when you
ReDim Preserve to a smaller size, then all
proceeds as above except that instead of copying for the size of the old array, VBScript only
copies for the size of the new array.
And that's enough for part 2 of this series. In part 3, we'll examine how VBScript objects are created and referenced and discover some important differences between how VBScript treats objects and arrays.