Review

First, we added the fundamental programming concept of the function. A function is a piece of code that can "stand alone"; it can be compiled separately from other functions, and provides some service that we can use via a mechanism known as a function call. The function that makes the call is known as the calling function, and the one it calls is known as the called function. Before we can call a function, we need to know what input values it needs and what it returns. This information is provided by a function declaration at the beginning of each function. The function declaration includes an argument list, which specifies input values that the called function uses (if any), and a return type, which specifies the type of the value that it produces when it's finished (if any). When we call a function, it executes until it reaches the end of its code or reaches a return statement, whichever comes first. When either of these events happens, the program continues execution in the calling function immediately after the place where the function call occurs. Ordinarily, as in our example, an argument to a function is actually a copy of the variable in the calling program, so that the called function can't modify the "real" value in the caller. Such an argument is called a value argument.[34]

[34] As this might suggest, there is another type of argument, which we'll get to in Chapter 6.

We also saw that function and variable names can be of any length, consisting of upper or lower case characters (or both), digits, and the special character underscore (_). To make it easier for the compiler to distinguish numbers from variable names, the first character can't be a digit. Also, a variable name can't be the same as a keyword, or name defined by the language; examples of keywords we've seen so far include if, for, and short.

After finishing the construction of our Average function, we saw how to use it by making a function call. Then we launched into an examination of the way that values in the calling function are converted into arguments in the called function, which required a detour into the software infrastructure.

We started this excursion by looking at the linker, which is used to construct programs from a number of functions compiled into separate object files. Next, we explored the notion of storage class, which determines the working lifetime of a variable. The simplest storage class is static. Variables of this class, which includes all variables defined outside any function, have storage assigned to them by the linker and retain the same address during the lifetime of the program. On the other hand, auto (for "automatic") variables are always defined in a function and are assigned storage on the stack when that function starts execution. The stack is the data structure that stores function arguments, local variables, and return addresses during the execution of a function; it's called that because it behaves like a spring-loaded stack of plates in a cafeteria, where the last one put on the top is the first one to be removed.

Then we noted that each variable, in addition to a storage class, has a scope, which is the part of a program in which the variable can be accessed. At this point, the scopes that are important to us are local scope and global scope. As you might guess, a global variable can be referred to anywhere, while a local variable can be accessed only in the function where it is defined. Although it may seem limiting to use local variables rather than global ones, programs that rely on global variables are very difficult to maintain, as a change anywhere can affect the rest of the program. Programs that limit the scope of their variables, on the other hand, minimize the amount of code that can be affected by a change in one place. Because local variables are only usable while in the function where they are defined, they can be stored on the stack; therefore, they don't occupy memory during the entire lifetime of the program.

Of course, local variables take up room while they're being used, which means that the stack has to have enough storage to hold all of the local variables for the current function and all of the functions that haven't finished executing. That is, the stack has to have enough room for all of the variables in the current function, the function that called the current function, the one that called that one, and so on up to the main function, which is always the top-level function in a C++ program. Since the amount of memory that is allocated to the stack is not unlimited, it's possible to run out of space, in which case your program will stop working. This is called a stack overflow, by analogy with what happens if you put too many plates on the cafeteria plate stack: it falls over and makes a mess. When using the compiler that comes with this book, it's unlikely that you'll ever run out of stack space unless you have a bug in your program. Some other compilers aren't as generous in their space allotments, so the likelihood of a stack overflow is less remote. The solution to this problem, should it arise, is to use another kind of storage allocation called dynamic storage; we'll see an example of this mechanism in Chapter 6.

Now that we've gone through that review, it's time to do an exercise to drive home some points about scope and storage classes.

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

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