Sams Teach Yourself C in 24 Hours (39 page)

BOOK: Sams Teach Yourself C in 24 Hours
3.39Mb size Format: txt, pdf, ePub

i= 1, j= 9

i= 2, j= 8

18 067231861x CH14 4.10.2000 11:03 AM Page 226

226

Hour 14

i= 3, j= 7

i= 4, j= 6

i= 5, j= 5

i= 6, j= 4

i= 7, j= 3

i= 8, j= 2

i= 9, j= 1

i=10, j= 0

Within the outer block: i=32

The purpose of the program in Listing 14.1 is to show you the different scopes
ANALYSIS
of variables in nested blocks. As you can see, there are two nested blocks in Listing 14.1. The integer variable i declared in line 6 is visible within the outer block enclosed by the braces ({ and }) in lines 5 and 19. Two other integer variables, i and j, are declared in line 11 and are visible only within the inner block from line 10 to line 16.

Although the integer variable i within the outer block has the same name as one of the integer variables within the inner block, the two integer variables cannot be accessed at the same time due to their different scopes.

To prove this, line 8 prints out the value, 32, contained by i within the outer block for the first time. Then, the for loop in lines 14 and 15 displays 10 pairs of values assigned to i and j within the inner block. At this point, there is no sign that the integer variable i within the outer block has any effects on the one within the inner block. When the inner block is exits, the variables within the inner block are no longer accessible. In other words, any attempt to access j from the outer block would be illegal.

Finally, the statement in line 17 prints out the value of i within the outer block again to find out whether the value has been changed due to the integer variable i within the inner block. The result shows that these two integer variables hide from each other, and no conflict occurs..

Function Scope

Function scope
indicates that a variable is active and visible from the beginning to the end of a function.

In C, only a goto label has function scope. For example, the goto label, start, shown in the following code portion has function scope:

int main()

{

int i; /* block scope */

.

.

.

start: /* A goto label has function scope */

18 067231861x CH14 4.10.2000 11:03 AM Page 227

Understanding Scope and Storage Classes

227

.

.

.

goto start; /* the goto statement */

.

.

.

return 0;

}

Here the label start is visible from the beginning to the end of the main() function.

Therefore, there should not be more than one label having the same name within the main() function.

Program Scope

A variable is said to have
program scope
when it is declared outside a function. For instance, look at the following code:

int x = 0; /* program scope */

float y = 0.0; /* program scope */

int main()

{

int i; /* block scope */

.

.

.

return 0;

}

Here the int variable x and the float variable y have program scope.

Variables with program scope are also called
global variables
, which are visible among all the source files that make up an executable program. Note that a global variable is declared with an initializer outside a function.

The program in Listing 14.2 demonstrates the relationship between variables with program scope and variables with block scope.

LISTING 14.2

The Relationship Between Program Scope and Block

TYPE

Scope

1: /* 14L02.c: Program scope vs block scope */

2: #include

14

3:

4: int x = 1234; /* program scope */

5: double y = 1.234567; /* program scope */

continues

18 067231861x CH14 4.10.2000 11:03 AM Page 228

228

Hour 14

LISTING 14.2

continued

6:

7: void function_1()

8: {

9: printf(“From function_1:\n x=%d, y=%f\n”, x, y);

10: }

11:

12: main()

13: {

14: int x = 4321; /* block scope 1*/

15:

16: function_1();

17: printf(“Within the main block:\n x=%d, y=%f\n”, x, y);

18: /* a nested block */

19: {

20: double y = 7.654321; /* block scope 2 */

21: function_1();

22: printf(“Within the nested block:\n x=%d, y=%f\n”, x, y);

23: }

24: return 0;

25: }

I have the following output shown on the screen after the executable 14L02.exe is created and run on my machine:

From function_1:

OUTPUT

x=1234, y=1.234567

Within the main block:

x=4321, y=1.234567

From function_1:

x=1234, y=1.234567

Within the nested block:

x=4321, y=7.654321

As you can see in Listing 14.2, there are two global variables, x and y, with pro-ANALYSIS gram scope; they are declared in lines 4 and 5.

In lines 7–10, a function, called function_1(), is declared. (More details about function declarations and prototypes are taught in the next hour.) The function_1() function contains only one statement; it prints out the values held by both x and y. Because there is no variable declaration made for x or y within the function block, the values of the global variables x and y are used for the statement inside the function. To prove this, function_1() is called twice in lines 16 and 21, respectively, from two nested blocks.

The output shows that the values of the two global variables x and y are passed to printf() within the function_1() function body.

Then, line 14 declares another integer variable, x, with block scope, which can replace the global variable x within the block of the main() function. The result made by the 18 067231861x CH14 4.10.2000 11:03 AM Page 229

Understanding Scope and Storage Classes

229

statement in line 17 shows that the value of x is the value of the local variable x with block scope, whereas the value of y is still that of the global variable y.

There is a nested block in lines 19 and 23, within which another double variable y, with block scope, is declared and initialized. Like the variable x within the main() block, this variable, y, within the nested block replaces the global variable y. The statement in line 22 displays the values of the local variables x and y on the screen

Because a global variable is visible among different source files of a program, using global variables increases your program’s complexity, which in turn makes your program hard to maintain or debug. Generally, it’s not recommended that you declare and use global variables, unless it’s absolutely necessary. For instance, you can declare a global variable whose value is used (but never changed) by several subroutines in your program. (In Hour 23, “Compiling Programs: The C Preprocessor,” you’ll learn to use the

#define directive to define constants that are used in many places in a program.)

Before I introduce file scope, let me first talk about the storage class specifiers.

The Storage Class Specifiers

In C, the
storage class
of a variable refers to the combination of its spatial and temporal regions.

You’ve learned about scope, which specifies the spatial region of a variable. Now, let’s focus on
duration
, which indicates the temporal region of a variable.

There are four specifiers and two modifiers that can be used to indicate the duration of a variable. These specifiers and modifiers are introduced in the following sections.

The
auto
Specifier

The auto specifier is used to indicate that the memory location of a variable is temporary. In other words, a variable’s reserved space in the memory can be erased or relocated when the variable is out of its scope.

Only variables with block scope can be declared with the auto specifier. The auto key-14

word is rarely used in practice, however, because the duration of a variable with block scope is temporary by default.

18 067231861x CH14 4.10.2000 11:03 AM Page 230

230

Hour 14

The
static
Specifier

The static specifier, on the other hand, can be applied to variables with either block scope or program scope. When a variable within a function is declared with the static specifier, the variable has a permanent duration. In other words, the memory storage allocated for the variable is not destroyed when the scope of the variable is exited, the value of the variable is maintained outside the scope. If execution ever returns to the scope of the variable, the last value stored in the variable is still there.

For instance, in the following code portion:

int main()

{

int i; /* block scope and temporary duration */

static int j; /* block scope and permanent duration */

.

.

return 0;

}

the integer variable i has temporary (auto) duration by default. But the other integer variable, j, has permanent duration due to the storage class specifier static.

The program in Listing 14.3 shows the effect of the static specifier on variables.

TYPE

LISTING 14.3

Using the static Specifier

1: /* 14L03.c: Using the static specifier */

2: #include

3: /* the add_two function */

4: int add_two(int x, int y)

5: {

6: static int counter = 1;

7:

8: printf(“This is the function call of %d,\n”, counter++);

9: return (x + y);

10: }

11: /* the main function */

12: main()

13: {

14: int i, j;

15:

16: for (i=0, j=5; i<5; i++, j--)

17: printf(“the addition of %d and %d is %d.\n\n”,

18: i, j, add_two(i, j));

19: return 0;

20: }

18 067231861x CH14 4.10.2000 11:03 AM Page 231

Understanding Scope and Storage Classes

231

The following output is displayed on the screen after the executable (14L03.exe) is run: This is the function call of 1,

OUTPUT
the addition of 0 and 5 is 5.

This is the function call of 2,

the addition of 1 and 4 is 5.

This is the function call of 3,

the addition of 2 and 3 is 5.

This is the function call of 4,

the addition of 3 and 2 is 5.

This is the function call of 5,

the addition of 4 and 1 is 5.

The purpose of the program in Listing 14.3 is to call a function to add two inte-ANALYSIS gers and then print out the result returned by the function on the screen. The function is called several times. A counter is set to keep track of how many times the function has been called.

This function, called add_two(), is declared in lines 4–10. There are two int arguments, x and y, that are passed to the function, and the addition of the two arguments is returned in line 9. Note that there is an integer variable, counter, which is declared with the static specifier in line 6. Values stored by counter are retained because the duration of the variable is permanent. In other words, although the scope of counter is within the block of the add_two() function, the memory location of counter and value saved in the location are not changed after the add_two() function is called and the execution control is returned back to the main() function. Note that the initialization of counter to 1 only takes place the first time add_two() is called; after that, it retains its previous value each time the function is called.

Therefore, the counter variable is used as a counter to keep track of the number of calls received by the add_two() function. In fact, the printf() function in line 8 prints out the value saved by the counter variable each time the add_two() function is called. In addition, counter is incremented by one each time after the printf() function is executed.

The for loop, declared in lines 16–18 within the main() function, calls the add_two() function five times. The values of the two integer variables, i and j, are passed to the add_two() function where they are added. Then, the return value from the add_two()
14

function is displayed on the screen by the printf() call in lines 17 and 18.

From the output, you can see that the value saved by counter is indeed incremented by one each time the add_two() function is called, and is retained after the function exits because the integer variable counter is declared with static. You can see that counter is only initialized to 1 once, when the add_two() function is called for the first time.

18 067231861x CH14 4.10.2000 11:03 AM Page 232

232

Hour 14

File Scope and the Hierarchy of Scopes

In the first part of this hour, I mentioned three of the four types of scopes: block scope, function scope, and program scope. It’s time now to introduce the fourth scope—
file
scope
.

In C, a global variable declared with the static specifier is said to have file scope. A variable with file scope is visible from its declaration point to the end of the file. Here the file refers to the program file that contains the source code. Most large programs consist of several program files.

The following portion of source code shows variables with file scope:

int x = 0; /* program scope */

static int y = 0; /* file scope */

static float z = 0.0; /* file scope */

int main()

{

int i; /* block scope */

.

.

.

return 0;

}

Here the int variable y and the float variable z both have file scope.

Figure 14.1 shows the hierarchy of the four scopes. As you can see, a variable with block scope is the most limited and is not visible outside the block within which the variable is declared. On the other hand, a variable with program scope is visible within all files, functions, and other blocks that make up the program.

Other books

The Shards by Gary Alan Wassner
The Dreams of Ada by Robert Mayer
Cosmopolitan Girls by Charlotte Burley
Scored by Lauren McLaughlin
Dirty Laundry by Rhys Ford
Keeper of the King's Secrets by Michelle Diener