ASPFAQs.com

4GuysFromRolla.com : ASP FAQS : Arrays

Question: How is an array stored in memory? I am interested in learning about the internals of an array!

 `This message is a replica of Bill Wilkinson's post to the ASP Messageboard on March 23rd, 2001[http://www.aspmessageboard.com/forum/Advanced.asp?M=182405&F=27&P=1]`

When you allocate an array -- say via `Dim ar(500)` -- the system allocates CONTIGUOUS memory sufficient to hold the requisite number of items (since VBS always starts arrays at zero, this means space for 501 items). ALL ITEMS ARE ALWAYS THE SAME SIZE.

Then, when you ask for a particular element in the array [say via `x=ar(76)`] the system simply multiplies the index [76 in the example] by the SIZE one item, adds that number to the address of the start of the array, and presto! It is addressing the proper spot in memory.

Now...the hard part...HOW BIG is each item in the array???

In a language such as C/C++/Java or even standard VB, the size of each item depends upon the *type* of the array elements. For example, if you asked for an array of 100 `int`s in C/C++/Java you would allocate 100 times 4 bytes, because an int is 4 bytes in those languages. If you allocated an array of 1000 `double`s, you'd allocate 1000 time 8 bytes, because guess how big a double is.

But VBScript and JScript are "typeless" languages. Right? Any element of any array can hold *any* data value. Right? So how does *that* work? How can the system know in advance how big each element should be?

Simple: In truth, every value in VBS and JS is an OLE VARIANT type. And what's a VARIANT look like? If you are into C/C++/Pascal, it's a "discriminated union". That is, the first two bytes contain a number (a short integer) that tells *how* to interpret the rest of the bytes! And then the rest of the bytes can be a boolean, byte, int [see `CInt`, only 16 bits], long [32 bit integer], float, double, or ... and here's the tricky part ... a *POINTER* to some more complex structure! Including pointers to STRINGS and pointers to objects!

So given the (actually fairly limited) range of possible "meanings" of a VARIANT, it shouldn't surprise you to find out that every VARIANT uses 16 bytes of memory.

And thus every variable uses 16 bytes of memory. *AND* thus every element of an array uses 16 bytes of memory!

So `Dim ar(500)` allocates `501 * 16` or 8016 bytes of memory.

"But, but, but..." you say, "what if I put a long string into each slot of the array? 8016 bytes might not even be enough to hold *one* of the strings, let alone 501 of them!"

Uh uh uh...go back and read what I wrote again: If the type of the data isn't one of the "primitive" (numeric, etc.) types, then the VARIANT holds a *POINTER* to the actual data! So when you do something like:

 `<%   ar = Array("this","is","a","demonstration")   Response.Write ar(3) %> `

This is what happens:

First of all, the system figures out that the array you are creating has size 4 (elements 0 through 3). So it allocates 4 times 16 bytes and points the variable `ar` to those 64 bytes.

Then it allocates space for a string containing `this` and puts the address of that string into slot 0 of the array; it sets the first two bytes of that slot to indicate that the VARIANT points to a string.

Then it allocates space for a string containing "is" and puts the address of that string into slot 1 of the array; it sets the first two bytes of that slot to indicate that the VARIANT points to a string.

Then it allocates space for a string containing "a" and puts the address of that string into slot 2 of the array; it sets the first two bytes of that slot to indicate that the VARIANT points to a string.

Then it allocates space for a string containing "demonstration" and puts the address of that string into slot 3 of the array; it sets the first two bytes of that slot to indicate that the VARIANT points to a string.

Then, in the next line, when it sees `ar(3)`, it picks up the address of the array. It sees the "3" as the element number, so it multiplies 3 times 16. It thus adds 48 to the array address. It picks up the 16 bytes of memory that appear at the calculated address. It looks at the VARIANT it thus got and sees that this is a STRING, so it extracts the StringAddress variant from the known spot in the VARIANT, knows that this is the address of some STRING, and now it can `Response.Write` the string.

Whew. Okay?

NOW...a quiz...

In that code, *what* does the variable name `ar` look like in memory? Don't answer in haste. Think about it.

Suppose the code looked like this:

 `<%   ar = Array("this","is","a","demonstration")   ar2 = ar %> `

What does variable `ar2` look like in memory? Hint: The same as variable `ar`.

There will be a quiz Monday. :-)

FAQ posted by Bill Wilkinson at 3/23/2001 7:19:15 PM to the Arrays category. This FAQ has been viewed 56,577 times.