2. Scope Rules
|
|
2.1 Storage Classes |
|
Every variable and function in C has two attributes: type and storage class. The four storage classes are automatic, external, register, and static, with corresponding keywords |
auto extern register static |
|
Scope Rules is the region in which a variable is valid. |
|
2.2 Internal Variables vs. External Variables |
|
Internal variables (= local variable) |
– Internal variables are defined inside of any function.
– Declarations of variables within blocks are implicitly of storage class automatic. |
|
External variables |
– External variables are defined outside of any function, and are thus potentionally available to many functions.
– Functions themselves are always external, because C does not allow functions to be defined inside other functions.
– When a variable is declared outside a function, storage is permanently assigned to it, and its storage class is extern. |
|
Example: global variable vs. local variable |
#include <stdio.h>
int a = 1, b = 2, c = 3; /* global variables */
int my_sum(void);
int main(void)
{
printf(“%d\n”, my_sum()); /* What is printed? */
printf(“%d, %d, %d\n”, a, b, c);
}
int my_sum(void)
{
int b, c; /* local variables */
a = b = c = 4; /* global b, c are masked */
return(a + b + c);
}
|
|
|
Example: external variable |
In file main.c
#include <stdio.h>
int a = 1, b = 2, c = 3; /* external variables */
int my_sum(void);
int main(void)
{
printf(“%d\n”, my_sum()); /* What is printed? */
printf(“%d, %d, %d\n”, a, b, c);
}
In file my_sum.c
int my_sum(void)
{
extern int a; /* look for it elsewhere */
int b, c; /* local variables */
a = b = c = 4; /* global b, c are masked */
return(a + b + c);
} |
|
|
Note: Definition vs. Declaration |
|
Note the distinction between a variable definition, which sets aside storage for the variable, and an extern declaration. The latter says: "This function uses an external variable with such-and-such a name and type that is defined elsewhere.” |
That is, the distinction between a definition and a declaration is to the memory allocation for the variable. |
Interval variable |
– int x; /* variable declaration, NO memory allocation */
– x = 0; /* Here, the memory will be allocated */ |
External variable |
– int x; /* variable definition with memory allocation because the variable is automatically set
as 0 */ |
|
2.3 Static Variables |
|
static keyword has two meanings, depending on where the static variable is declared. |
Outside a function, static variables/functions only visible within that file, not globally (cannot be extern’ed). External static thus provides a way to hide names to others. |
Inside a function, static variables: |
– are still local to that function
– are initialized only during program initialization
– do not get reinitialized with each function call |
|
Example: static variable |
|
void f(void)
{
static int cnt = 0;
++cnt;
printf(“cnt = %d\n”, cnt);
} |
|
|
The first time the function is invoked, the variable cnt is initialized to zero. On function exit, the value of cnt is preserved in memory. Whenever the function is invoked again, cnt is not reinitialized. |
|
2.4 Static External Variable |
|
The difference is that static external variables are scope-restricted external variables. The scope is the remainder of the source file in which they are declared. Thus, they are unavailable to functions defined earlier in the file ore to functions defined in other files. |
|
Example: static variable |
|
void f(void)
{
..... /* v is not available here */
}
static int v;
void g(void)
{
..... /* v is not available here */
}
|
|
|
|
Example |
|
/* A family of pseudo random number generators. */
#define INITIAL_SEED 17
#define MULTIPLIER 25173
#define INCREMENT 13849
#define MODULUS 65536
#define FLOATING_MODULUS 65536.0
static unsigned seed = INITIAL_SEED;
/* external, but private to this file */
unsigned rani(void) /* return a random sequence */
{
seed = (MULTIPLIER*seed+INCREMENT)%MODULUS;
return seed;
}
double ranf(void) /* return a floating value [0, 1] */
{
seed = (MULTIPLIER*seed+INCREMENT)%MODULUS;
return (seed/FLOATING_MODULUS);
} |
|
|
2.5 Register Variables |
|
A register declaration advises the compiler that the variable in question will be heavily used. The idea is that register variables are to be placed in machine registers, which may result in smaller and faster programs. But compilers are free to ignore the advice. |
Only a few variables in each function may be kept in registers, and only certain types are allowed. Excess register declarations are harmless |
|
int f(register unsigned n, register char c)
{
register int x;
...
} |
|
|
Register Variables |
– During execution, data processed in registers
– Explicitly store commonly used data in registers – minimize load/store overhead
– Can explicitly declare certain variables as registers using register keyword |
must be a simple type (implementation-dependent)
only local variables and function arguments eligible
excess/unallowed register declarations ignored, compiled as regular variables |
– Registers do not reside in addressed memory; pointer of a register variable illegal |
|