Published: Wednesday, April 11, 2001
Variables, Values, and Arrays in VBScript (Part 2 of a 3-Part Series), Part 2
By Bill Wilkinson
Read Part 1
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!
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 ar(0,y)
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:
addressOfElementXYofArrayAr = addressOfArrayAr + ( ( y * 16 * ( UBound(ar,1) + 1 ) ) + (x * 16) )
|
Let's look at that a piece at a time:
That's how many elements there are in each row. For our array ar,
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:
16 * ( UBound(ar,1) + 1 )
|
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
bytes - 2 * 16.] We find the address of the beginning of the y row
by multiplying by y:
y * 16 * ( UBound(ar,1) + 1 )
|
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
element ar(x,y).
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.
Happy Programming!
By Bill Wilkinson
Read Part 1 of this three-part series!
Read Part 3 of this three-part series!