When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips

Sections:
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
XML Info
Information:
Feedback
Author an Article
ASP ASP.NET ASP FAQs Message Board Feedback
Print this page.
Published: Tuesday, March 28, 2000

Variables and Values in VBScript

By Bill Wilkinson


Introduction
One of the most used but least understood features of VBScript is the flexibility of variables and values as used throughout the language. This short series of articles will hopefully remove some of the mysteries of VBScript for you.

- continued -

In this first article, we will explore the basic principles of variables and values. In succeeding articles, we will discuss arrays, user-defined objects, and more.

The second part, Variables, Values, and Arrays in VBScript, examines how VBScript handles single and multi-dimensional arrays.

Finally, the third part, Object References in VBScript, looks at object references and how VBScript handles copies of objects and arrays.

Introduction to Variants:
If you are a C or C++ programmer experienced in COM and OLE, you will hopefully know what I mean when I say that every variable and every value (except certain intermediate values) in VBScript is actually an instance of an OLE VARIANT type. If you don't know what that means, read on.

To begin, let's talk about what variables look like in most other languages. In C and C++ and Java and Pascal and even Visual Basic, you typically tell the language processor (compiler or interpreter) what kind or type of variable you are creating. For example, you would do the following to create a variable named myNumber that is capable of holding values from roughly -2,000,000,000 to +2,000,000,000 in these various languages (although the actual range may depend on the particular compiler you are using):

  • C/C++/Java: int myNumber;
  • Visual Basic: Dim myNumber AS Long
  • Pascal: myNumber : Integer;

But in VBScript, all variables are always of the same kind or type, the aforementioned VARIANT type. And just what is a VARIANT? Ahhh… A VARIANT is a special kind of data structure that is capable of holding or referring to any kind of data that OLE (or VBScript) understands! And what it holds can vary, from moment to moment! Actually, you may have seen this in VBScript code, such as:

<%
  uDate = Request.Form("userDate")
  uDate = CDate( uDate )
%>

If you didn't already know it, be aware that Request.Form("fieldname") and Request.QueryString("fieldname") always return a string! This only makes sense: The browser certainly doesn't know the intended use of any given form field, so it always sends all data on to the server as a string. And just because a string contains 17 November 2001 doesn't mean, to the server, that it is necessarily a date. So, if you want to ensure that a given form field contained a date - or if you need to do datewise manipulation of a value from such a field - you use the CDate function. So that same variable first held a string and then held a date/time value! This would be impossible with the built-in data types found in most other languages.

How does it work?
Inside your computer's CPU (presumably, a Pentium processor, unless you are lucky enough to be running ChiliSoft ASP on Solaris or AIX?), there are certain data types that it understands in ways that are built into its hardware. Because these are so fundamental to computer processing, they are sometimes called "primitive" types. When a primitive type appears in your computer's memory (in RAM or ROM or even on a disk), it occupies a certain number of bytes, which number is fixed for each primitive type.

Examples: A C/C++/Java int (VB Long, Pascal Integer, as shown above) always occupies four (4) bytes of memory. A short format floating point number (which can represent numbers with a decimal point with roughly 6 or 7 digit accuracy) also uses four bytes. A long format floating point number (also known as a "double", having roughly 14 or 15 digits of precision) needs 8 bytes. Various other primitive types occupy from one to eight bytes of memory. (Theoretically, a boolean needs only one bit of memory, but in practice most computer languages use one or more bytes because that fits the computer CPU architecture better.)

In the "conventional" languages, then, when you create a variable of a particular type (as in the various integer examples, above), that variable is always exactly that size. You can't store a double in a variable that was allocated as an integer (or vice versa—even though the 4-byte integer would fit in the 8 byte double, the languages don't allow it for reasons too complex to go into here).

But then there is VARIANT. If you happen to know Pascal, you might recognize a VARIANT as simply a "varying record." C and C++ don't have any built-in type that corresponds (and you really can't do this in Java, at all), but sometimes you might hear the term "discriminated union" used to describe this kind of structure. Briefly, a VARIANT always occupies 16 bytes of memory but only uses what is needed. And the first two bytes of the VARIANT always indicate what the other 14 bytes are holding!

So if you do something in VB like this:

Dim num
num = 731

The variable num will have its first two bytes set to the number 2 (indicating a short integer) and two other bytes of the 16 (a particular two—and which two of the 16 never changes, but we don't care which two for this discussion) will hold the integer number 731. If you do:

Dim num
num = 12345678

then the first two bytes of num will contain the number 3 and a particular four bytes of the 16 will contain the long integer value 12345678. If you are curious about what all the possible values of those first two bytes can be with VBScript, then look at the documentation in the VBScript reference manual for the VarType function, where all the values are listed (view the technical docs). (Not relevant to this discussion, but of interest to C/C++ programmers, perhaps: There are many more possible values for those two bytes within the definition of an OLE VARIANT data type. But VBScript uses only the values noted under the documentation for VarType.)

So now we can understand how the code we looked at above works:

<%
  uDate = Request.Form("userDate")
  uDate = CDate( uDate )
%>

The first assignment to the variable uDate will set its first two bytes to 8, indicating that the VARIANT contains a string. The second assignment changes that number to a 7, indicating that the variable now contains a Date/Time value. And, in the process, the other bytes of the VARIANT are changed as needed.

"But wait," I can hear you say, "if I have a string of 100 characters how do they all fit into those 16 bytes of the VARIANT?" Ahhh…you knew there had to be trick in here! And the trick is simple: For all except the primitive data types (look above to see what they are), the VARIANT contains a pointer to the actual data! So if you look at the list of type numbers in the documentation for VarType, you will hopefully understand that the following numbers do not represent primitive types and so the rest of the VARIANT will contain a pointer to the actual data:

VarType Values that Use Pointers
8vbStringA pointer to the string contents
9vbObjectA pointer to an ActiveX object
10vbErrorA pointer to an Error object
12vbVariantPlease don't ask about this one yet!
13vbDataObjectA DAO object (may not be used in ASP?)
8192vbArrayAn array

Looking again at the uDate function example, above, we can see that a given variable can sometimes hold a VARIANT that contains a primitive value and sometimes one that contains a pointer to some more extended data. Truly, VBScript variables, through the mechanism of the VARIANT, are extremely flexible.

And now, before we leave this subject for this week, let's look at an interesting little ASP page:

<HTML><BODY>
<%
  Set d1 = Server.CreateObject("Scripting.Dictionary")
  d1.Add "first", "added via d1.add"
  Set d2 = d1
  d2.Add "second", "this via d2.add"

  Response.Write "from d1(second) we get: " & d1("second") & "<P>"
  Response.Write "from d2(first) we get: " & d2("first") & "<P>"
%>
</BODY><HTML>

I won't make you actually try that code, though I do encourage you to do so. And even experiment with it some. But to save you time, here is what that page looks like in a browser:

from d1(second) we get: this via d2.add
from d2(first) we get: added via d1.add

Do you understand the implications of that? The "objects" referenced by the variables d1 and d2 are actually one and the same object! So doing:

Set d2 = d1

did not copy the object referenced by d1. Instead, only the pointer that d1 contains is copied to a pointer in d2. The actual object does not move, is not affected by the copy, and remains fully accessible to both variables.

Start considering the implications of that seemingly simple action. And then next time we can discuss how this relates to other features of VBScript and start discussing how arrays work.

Happy Programming!

  • By Bill Wilkinson


  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article