Understanding Variable Scope

The final topic we'll discuss in this chapter is variable scope—in other words, where variables exist. This is pertinent to functions because variables within a function are not accessible by code outside a function. And, for that matter, variables outside a function are not necessarily accessible inside the function.

Understanding Static Variables

Variables within functions are different not only because of variable scope but also because they can be static. Let's start with this example:

void up_one (void) {
   int num = 0;
   printf ("%d
", ++num);
}

Even though num is incremented with each up_one() call, its ending value will only be 1 because it's reinitialized to 0 each time the function is called. In other words, the num variable does not retain any changes.

This behavior can be altered by using the static keyword:

void up_one (void) {
   static int num = 0;
   printf ("%d
", ++num);
}

Each call to this function will now increase the value of num by 1. So instead of continually printing 1s, you would see 1, 2, 3, and so on, with each call to the function.

Global variables are automatically static, and whatever changes they experience will be retained, inside or outside a function.


There are two realms of scope to deal with: global, which means that a variable is available inside and outside any function (it's available everywhere); and, local, which refers to the area inside a particular function. Note that this means each function has its own local scope. A variable existing within one function does not exist inside another.

To create a global variable, you just need to define it—as you would any other variable—outside of any function definition, including main. The following (rather trivial) example will demonstrate this.

To work with variable scope

1.
Create a new file or project in your text editor or IDE.

2.
Type the standard beginning lines of code (Script 7.6):

/* global.c - Script 7.6 */
#include <stdio.h>

Script 7.6. Unless special steps are taken, variables within a function are separate entities than those outside the function, even if they have the same name.


3.
Add a function prototype:

void other_function (void);

As you can tell, this other_function() won't do too much: it takes no arguments and returns no values.

4.
Define a global variable:

int g_num = 100;

The variable, called g_num, is an integer with a value of 100. Because it has been defined outside any function, it has global scope.

5.
Begin the main function:

int main (void) {

6.
Define a local variable:

int num = 20;

This variable will be local to the main function, meaning it only exists within the confines of main.

7.
Print both the local and global variables:

printf ("Inside of the main function,
 the global g_num is %d. The local
 num is %d.
", g_num, num);

This print statement shows the current value of both the local (num) and global (g_num) variables.

8.
Call the other_function():

other_function();

This statement will execute the code within the other_function() definition.

9.
Print the values of the local and global variables once again:

printf ("After calling the
 other_function, the global g_num is
 %d. The local num is %d.
", g_num,
 num);

So that you can track how each variable changes, their values are printed both before and after calling the second function.

10.
Complete the main function:

getchar();
return 0;
}

11.
Begin defining the second function:

void other_function (void) {

12.
Create a new variable, local to this function:

int num = 600;

Although it has the same name as the num variable found in the main function, this is an entirely separate variable with a separate value.

13.
Change the value of the global variable:

g_num = 0;

Unlike the two num variables, g_num's scope pervades all functions. So changing its value within any one function has the effect of changing its value everywhere.

14.
Print both variable values:

printf ("Inside of the other_function
 function, the global g_num is %d.
 The local num is %d.
", g_num,
 num);

The Black Box
Theory of Programming

When making more modular code by defining your own functions, you should try to follow the black box theory of programming, which is to say that what happens inside a function should be irrelevant to the code calling it. Or, to put another way: when creating your own functions, they should be written so that they take certain arguments, return a certain value, and have no other contingencies outside the function.

With respect to variable scope, programs are more stable when they are divided into functions that don't exchange data using global variables but rather through their clearly defined arguments and return values. Such code is much easier to understand and maintain. Thus, the limited scope of variables is a good thing.


15.
Complete the second function:

return;
}

Because this function returns no values, an empty return statement is used.

16.
Save the file as global.c, compile, and debug as necessary.

17.
Run the executable application (Figure 7.11).

Figure 7.11. Notice that local variables return their value within each function while global variables can exist and be altered within any function.


✓ Tips

  • Even when you use a variable in a function call, like this:

    int my_var = 20;
    some_function (my_var);
    

    you are not truly passing that variable to the second function but rather that variable's value. In the above code, the my_var variable still doesn't exist within the some_function() function.

  • You might think that since global variables exist everywhere, it would be best to use nothing but global variables. Although this makes it easier for you, the programmer, it's poor form. If a variable is only necessary within a single function, there's no reason for it to have global scope.

  • Be extra careful not to give global and local variables the same name. If you do, the local variable will take precedence within that function and the global variable will not exist for all practical purposes. Some programmers avoid this by starting global variable names with a small g, to indicate their global status.

  • Global variables are only truly global to functions defined after they have been declared. But since it's standard to define global variables before any functions (or to place them in a header file), this is rarely an issue.

  • Another confusing aspect of recursion is that each iteration of the function has its own variables local to that function call. This means that the compiler and system must store and track these variables, associated with each level of recursion.

  • One way to work around variable scope is to pass values to a function by reference (passing its address instead of its value). This requires pointers, which you'll learn about in Chapter 9.

  • Variables also have a class status: either permanent or temporary. Global and static variables are always permanent, meaning that memory is set aside for them during the entire execution of an application. Memory is used for temporary variables as needed, such as within the execution of a single function.


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

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