Skip to content

section6_scope_rules

Fábio Gaspar edited this page Jan 15, 2019 · 1 revision

Scope rules

The scope of external variables and functions lasts from the point at which it is declared to the end of the file being compiled.

/* code ... */

void foo() {
	a = 10;
}

int a; /* Visible starting here */

void goo() {
	a = 5;
}

/* end of the file */

In the example above we see the definition of the foo() function and the goo() function, with the definition of an integer variable a in between. Altough a is a global variable, it's not visible in the foo() function because is declared and defined afterwards.

demo.c: In function ‘foo’:
demo.c:5:2: error: ‘a’ undeclared

This principle is also valid for functions. The function goo() is not visible in the foo() function.

Refering to external variables/functions before they are defined is a common problem. The solution is declaration. Before diving into that, let's recall the difference between declaring and defining.

  • Declaration: The declaration of an external variable announces the variable properties, mainly its type.
  • Definition: The definition of an external variable, not only defines it, but also causes storage to be set (memory is reserved for the variable).

Declaring variables

This is how variables are defined and optionally initialized.

int a;
int b = 10;

In order to just declare a variable you must use the extern keyword.

extern int a;

Extern variables are more useful when you use multiple source files, which weren't covered yet. The program above could be fixed by simply moving the variable definition to the top pf the source file, or at least, above foo and goo. But, for the sake of demonstration, let's illustrate the extern keyword.

/* code ... */
extern int a;

void foo() {
	a = 10;
}

int a; 

void goo() {
	a = 5;
}

The variable declaration must be put above any reference to the variable.

Declaring functions

The extern keyword can also be used with functions. However, every function declaration has the external keyword implicit. The following declarations are both valid and equivalent.

int foo(int arg1);
extern int foo(int arg1);
void foo();
void goo();
void hoo();

int main() {
	foo();
	hoo();
}

void foo() {
	goo();
}

void goo() {
	/* ... */
}

void hoo() {
	/* ... */
}