Working with Functions in C: Global Variables

It is now time to tie together many of the principles you have learned in this chapter, as well as learn some new ones. Take Program 7.7, which converted a positive integer to another base, and rewrite it in function form. To do this, you must conceptually divide the program into logical segments. If you glance back at that program, you see that this is readily accomplished simply by looking at the three comment statements inside main. They suggest the three primary functions that the program is performing: getting the number and base from the user, converting the number to the desired base, and display- ing the results.

You can define three functions to perform an analogous task. The first function you call is getNumberAndBase. This function prompts the user to enter the number to be converted and the base, and reads these values in from the terminal. Here, you make a slight improvement over what was done in Program 7.7. If the user types in a value of base that is less than 2 or greater than 16, the program displays an appropriate message at the terminal and sets the value of the base to 10. In this manner, the program ends up redisplaying the original number to the user. (Another approach might be to let the user reenter a new value for the base, but this is left as an exercise.)

The second function you call is convertNumber. This function takes the value as typed in by the user and converts it to the desired base, storing the digits resulting from the conversion process inside the convertedNumber array.

The third and final function you call is displayConvertedNumber. This function takes

the digits contained inside the convertedNumber array and displays them to the user in the correct order. For each digit to be displayed, a lookup is made inside the baseDigits array so that the correct character is displayed for the corresponding digit.

The three functions that you define communicate with each other by means of global variables. As noted previously, one of the fundamental properties of a local variable is that its value can be accessed only by the function in which the variable is defined. As you might expect, this restriction does not apply to global variables. That is, a global variable’s value can be accessed by any function in the program.

The distinguishing quality of a global variable declaration versus a local variable dec- laration is that the former is made outside of any function. This indicates its global nature—it does not belong to any particular function. Any function in the program can then access the value of that variable and can change its value if desired.

In Program 8.14, four global variables are defined. Each of these variables is used by at least two functions in the program. Because the baseDigits array and the variable nextDigit are used exclusively by the function displayConvertedNumber, they are not defined as global variables. Instead, these variables are locally defined within the function displayConvertedNumber.

The global variables are defined first in the program. Because they are not defined within any particular function, these variables are global, which means that they can now be referenced by any functionin the program.

Program 8.14   Converting  a Positive  Integer to Another Base

// Program to convert a positive integer to another base

#include <stdio.h>

int     convertedNumber[64];

long int numberToConvert;

int     base;

int     digit = 0;

void getNumberAndBase (void)

{

printf (“Number to be converted? “);

scanf (“%li”, &numberToConvert);

printf (“Base? “);

scanf (“%i”, &base);

if ( base < 2 || base > 16 ) {

printf (“Bad base – must be between 2 and 16\n”);

base = 10;

}

}

void convertNumber (void)

{

do {

convertedNumber[digit] = numberToConvert % base;

++digit;

numberToConvert /= base;

}

while ( numberToConvert != 0 );

}

void displayConvertedNumber (void)

{

const char baseDigits[16] =

{ ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’,

‘8’, ‘9’, ‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’ };

int  nextDigit;

printf (“Converted number = “);

for (–digit; digit >= 0; –digit ) {

nextDigit = convertedNumber[digit];

printf (“%c”, baseDigits[nextDigit]);

}

printf (“\n”);

}

int main (void)

{

void getNumberAndBase (void), convertNumber (void), displayConvertedNumber (void);

getNumberAndBase ();

convertNumber ();

displayConvertedNumber ();

return 0;

}

Program 8.14   Output

Number to be converted? 100

Base? 8

Converted number = 144

Program 8.14   Output (Rerun)

Number to be converted? 1983

Base? 0

Bad base – must be between 2 and 16

Converted number = 1983

Notice how the wise choice of function names makes the operation of Program 8.14 clear. Spelled out directly in the main routine is the function of the program: to get a number and a base, convert the number, and then display the converted number. The much improved readability of this program over the equivalent one from Chapter 7 is a direct result of the structuring of the program into separate functions that perform small, well-defined tasks. Note that you do not even need comment statements inside the main routine to describe what the program is doing—the function names speak for them- selves.

The primary use of global variables is in programs in which many functions must access the value of the same variable. Rather than having to pass the value of the variable to each individual function as an argument, the function can explicitly reference the variable instead. There is a drawback with this approach. Because the function explicitly references a particular global variable, the generality of the function is somewhat

reduced. So, every time that function is to be used, you must ensure that the global vari- able exists, by its particular name.

For example, the convertNumber function of Program 8.14 succeeds in converting only a number that is stored in the variable numberToConvert to a base as specified  by the value of the variable base. Furthermore, the variable digit and the array convertedNumber must be defined. A far more flexible version of this function would allow the arguments to be passed to the function.

Although the use of global variables can reduce the number of arguments that need to be passed to a function, the price that must be paid is reduced function generality and, in some cases, reduced program readability. This issue of program readability stems from the fact that if you use global variables, the variables that are used by a particular function are not evident simply by examining the function’s header. Also, a call to the particular function does not indicate to the reader what types of parameters the function needs as inputs or produces as outputs.

Some programmers adopt the convention of prefixing all global variable names with the letter “g”. For example, their variable declarations for Program 8.14 might look like this:

int     gConvertedNumber[64];

long int gNumberToConvert;

int     gBase;

int     gDigit = 0;

The reason for adopting such a convention is that it becomes easier to pick out a global variable from a local one when reading through a program. For example, the statement

nextMove = gCurrentMove + 1;

implies that nextMove is a local variable and gCurrentMove is a global one. This tells the reader of this line about the scope of these variables and where to look for their declara- tions.

One final thing about global variables. They do have default initial values: zero. So, in the global declaration

int gData[100];

all 100 elements of the gData array are set to zero when the program begins execution.

So remember that while global variables have default initial values of zero, local vari- ables have no default initial value and so must be explicitly initialized by the program.

Source: Kochan Stephen G. (2004), Programming in C: A Complete Introduction to the C Programming Language, Sams; Subsequent edition.

Leave a Reply

Your email address will not be published. Required fields are marked *