Previous Table of Contents Next


Chapter 5
Simplified Variable Declarations

Deck: Follow these tips for unlimited visibility in your C declarations

by Paul Conte

An object's scope is something you can't C very clearly in source code. Or should I say you can't code scope clearly in C source? If you can't quite C where I'm headed, it's because we're just beginning a winding tour through the maze of C object visibility. Follow closely, and by the time we exit the maze, you'll have a simple map for the shortest route out.

C, like many languages, lets an identifier x refer to different objects (e.g., storage locations for variables) at different places in the source code. As a simple case, the two declarations of x below refer to different variables.

int x;


main( void ) {
int x;
...
}


void func1( void ) {
...
}

Let's say the first x refers to a storage location we'll call S1, and the second x refers to a storage location we'll call S2. The scope of the S1 object (storage location) is simply the region (i.e., lines) of source code where references to x are references to S1; likewise, the scope of the S2 object is the region of source code where references to x are references to S2. In this example, the scope of S1 (the first x) is everywhere outside the main function, and the scope of S2 (the second x) is only within the main function. Obviously, for the program to be clear, these two regions of the program can't overlap; each reference to x must refer to just one of the storage locations. Scope is also called "visibility" because you can "see" an object (e.g., read or change a storage location) only within its scope. In this chapter, I use "visibility" for the general concept and "scope" to refer to C's specific lexical scope attribute.

The C-nic Route

The concept of visibility is simple and useful. Among other uses, distinct regions of object visibility let you use identifiers in different parts of your code without worrying about whether the same identifier, used for different purposes, unintentionally refers to the same object. But why be merely simple and useful when you can be clever and brave, too? Take your first left turn into the C labyrinth.

C splits the single concept of visibility into scope and linkage, with scope referring to the region of program text within which an identifier's characteristics are understood. C's linkage term refers to the connection between identifiers in independently compiled translation units. Expressing visibility with two attributes instead of one may help C compiler writers, but it makes it more difficult for programmers to determine which object an identifier references. I'll try to map out C's rules while noting some language flaws that lead to C's problems. Then I'll mark an easy path to declaring variables and functions with the desired visibility.

C's rules for function visibility are simple: If you specify static storage class, a function is visible throughout the source file in which it's defined, but not in other source files. With extern or no storage class specifier, a function is visible throughout the program (i.e., across all files), and you can call it from anywhere. These rules lead to my first suggestion: Declare functions static if you intend to call them only from within the same source file.

C's rules for variable visibility are far more complex than those for function visibility. I've listed these rules in a table (Figure 5.1) that shows, for any variable declaration, where that variable is visible. I've also listed C's scope and linkage attributes and whether the declaration causes storage to be allocated (in C terminology, whether it is a definition as well as a declaration). You can use this guide to help you understand some of the mysterious changes that can occur when a C variable has unexpected visibility. You also may need it to follow my next few examples, but later I'll show you a far more useful table for C programming.

Figure 5.1 Visibility of C Variables DECLARED OR REFERENCED INSIDE A BLOCK (function or nested block):
Where Storage Initial Storage Scope/Linkage Visibility
specified class value allocation
1. Declared (none) Yes Yes Block scope, Within same block, including all
in block auto No Yes no linkage nested blocks, except
register any nested block (and its
static nested blocks) with an identical identifier without extern
2. Declared extern No CASE A: Enclosing scope has identical, visible
in block identifier — same scope, linkage, allocation, visibility as the matching identifier
CASE B: Otherwise, same as if declared extern outside function (see 7, below)
3. Declared extern Yes ILLEGAL
in block declaration
4. Not declared but referenced in block CASE A: Enclosing scope has identical, visible identifier declared in the same source file prior to the reference — same as if declared extern in block (see 2, above)
CASE B: Otherwise, ILLEGAL declaration
EXTERNAL DECLARATIONS (declared outside any function):
Which Storage Initial Storage Scope/Linkage Visibility
declaration class value allocation
5. First (none) Yes Yes File scope Rest of file except any
declaration No external block (and its nested blocks) with an identical identifier declared without extern, and blocks it contains and Other files with an identical external linkage identifier declared in them (No other file may allocate (define) an identical external linkage identifier.)
6. First static Yes Yes File scope, Rest of file except any
declaration No internal linkage block (and its nested blocks) with an identical identifier declared without extern, and blocks it contains
7. First extern Yes Yes File scope, Rest of life except any
declaration external linkage block (and its nested blocks) with an identical identifier declared without extern, and blocks it contains and Other files with an identical external linkage identifier declared in them (One other file must have an identical external linkage identifier allocated (defined) in it.)
8. First extern Yes Yes Same as if declared outside function
declaration without extern or static (see 5, above)
9. Second or Must have same Same scope, linkage, allocation, and
later type and linkage visibility as first declaration
declaration as first declaration


Previous Table of Contents Next