The Disadvantages of Global Variables

Now that we've cleared up the question of when different types of variables are initialized, let's continue with the distinction between global and local variables. You may be surprised that a programmer would accept the limitation of allowing certain variables to be accessed only in certain functions. Surely it's more powerful to be able to access anything anywhere. Isn't it?

Let me tell you a little story about the "power" of global variables. Unlike the one about the funny odometers, this one is true.

Using a Very Primitive BASIC Language

In the late 1970s, I worked for a (very) small software house where I developed a database program for the Radio Shack TRS-80 Model III computer. This computer was fairly powerful for the time; it had two 79K floppy disks and a maximum of 48K memory. The database program had to be able to find a subset of the few thousand records in the database in a minute or so. The speed of the floppy drive was the limiting factor. The only high-level language that was available was a BASIC interpreter clearly related by ancestry to QBASIC, the BASIC that comes with MS-DOS, but much more primitive; for example, variable names were limited to 2 characters.[31] There was also an assembler, but even at that time I wasn't thrilled with the idea of writing a significant application program in assembly language. So we were stuck with BASIC.

[31] That is, two significant characters; you could have names as long as you wanted, but any two variables that had the same first two characters were actually the same variable.

Actually, that wasn't so bad. Even then, BASIC had pretty good string manipulation functions (much better than the ones that come with C) and the file access functions, although primitive, weren't too hard to work with for the application in question. You could read or write a fixed number of bytes anywhere in a disk file, and since all of the records in a given database were in fact the same length, that was good enough for our purposes. However, there were a couple of (related) glaring flaws in the language: there were no named subroutines (like functions in C++), and all variables were global.

Instead of names, subroutines were addressed by line number. In TRS-80 BASIC, each line had a number, and you could call a subroutine that started at line 1000 by writing "GOSUB 1000". At the end of the subroutine, a "RETURN" statement would cause control to return to the next statement after the GOSUB.

While this was functional in a moronic way, it had some serious drawbacks. First, of course, a number isn't as mnemonic as a name. Remembering that line 1000 is the beginning of the invoice printing routine, for example, isn't as easy as remembering the name PrintInvoice. In addition, if you "renumbered" the program to make room for inserting new lines between previously existing lines, the line numbers would change. The second drawback was that, as the example suggests, there was no way to pass arguments to a subroutine when it was called. Therefore, the only way for a subroutine to get input or produce output was by using and changing global variables. Yet another problem with this line-numbered subroutine facility was that you could call any line as a subroutine; no block structure such as we have in C++ was available to impose some order on the flow of control.

With such an arrangement, it was almost impossible to make a change anywhere in even a moderately large program without breaking some subroutine. One reason for this fragility was that a variable could be used or changed anywhere in the program; another was that it was impossible to identify subroutines except by adding comments to the program, which could be out of date. So almost any change could have effects throughout the program.

The Solution to My Problem with BASIC

After some time struggling with this problem, I decided to end it, once and for all, by adding named subroutines with arguments and local variables to the language. This made it possible to maintain the program and we ended up selling several hundred copies of it over a couple of years. Besides, fixing the language was fun.

The moral? There's almost always a way around a limitation of a computer language, although it may not be worth the effort to find it. Luckily, with C++, adding functionality is a bit easier than patching BASIC in assembly language.

A Scope Defines a namespace

Before we finish with our discussion of scope, I should point out something that may not be obvious to you. Every scope defines a new namespace. This is why local variables in different functions don't clash with one another: since every function has its own scope, it also has its own namespace, so a local variable in one function is distinct from any local variables in other functions that have the same name.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset