title: “C Variable Scope” description: “Let’s talk about how C handles variable scope” pubDate: “2023-04-09” heroImage: “/placeholder-hero.jpg”
C Linkage
Storage Class
auto
automatically return the memory
- An auto variable has automatic storage duration, block scope and no linkage
static
limits the scope of a variable
- a
staticvariable is initialized only once, prior to program execution - A
staticvariable declared inside a function is shared by all calls function, including recursive calls. - A function may return a pointer to a
staticvariable.
Note:
staticvariables have0as default values.autovariables do not have default values.
static int i; // no access to i in other files
void f1(void){
//has access to i
}
void f2(void){
//has access to i
}
- use
staticfor reasons of efficiency:
char digit_to_hex_char(int digit){
static const char hex[] = "123456789ABCDEF";
return hex;
}
extern
tells the compiler the definition is somewhere else
- NOT a definition since it does not allocate memory space
extern int i; // not a definition
extern int i = 0; // definition
// the following two declarations are as effective
extern int i = 0;
int i = 0;
extern int i; // static storage duration, file scope,? linkage
void f(void){
extern int i; // static stroage duration, block scope,? linkage
}
- if the variable is previously declared as
static, the linkage will be internal - otherwise,
external
register
tells the compiler the variable will be frequently used. put it in register
- the
registerstorage class is legal only for variables declared in a block - a
registervariable has the same storage duration, scope, and linkage as an auto variable. - since registers don’t have addresses, it’s illegal to use the
&operator to take the address of aregistervariable
NOTE:
- Nowadays, compiler could usually do a better job when it optimizes your program
- Still, you can use register to prevent the value changed by pointer
extern const unsigned long int a[10];
const char month[];
Every variable in a C program has three properties
- Storage
- Scope
- Linkage
Storage Duration
- Automatic storage duration
- Memory for variable is allocated when the surrounding block isexecuted and deallocated when the block terminal
- Static storage duration
NOTE: When you declare a
static variableinside a function, you change the storage duration of the variable
Scope
- Local Scope
- File Scope
Linkage
- External Linkage
- the entire program
- over several files
- Internal Linkage
- within a single file
- No Linkage
- within a function (local var)
int i; // static storage duration, file scope, external linkage
void f(void){
int j; // automatic storage duration, block scope, no linkage
}
NOTE:
- Variables declared inside a block have automatic storage duration, block scope and no linkage
- Variables declared outside a block have static storage duration, file scope, and external linkage
Summary
int a;
extern int b;
static int c;
void f(int d, register int e){
auto int g;
int h;
static int i;
extern int j;
register int k;
}
| Name | Storage Duration | Scope | Linkage |
|---|---|---|---|
| a | static | file | external |
| b | static | file | * |
| c | static | file | internal |
| d | automatic | block | none |
| e | automatic | block | none |
| g | automatic | block | none |
| h | automatic | block | none |
| i | static | block | none |
| j | static | block | * |
| k | automatic | block | none |
NOTE:
*means that the definition of the variable is somewhere else. Therefore, there linkages are unknown here.
Type Qualifiers
const
- the following code is invalid since the length of an array needs defining during the compile time.
- Use macro in this case
const int n = 10;
int a[n]; // WRONG
volatile
do not optimize a variable
- tells the compiler that the variable may change unexpectedly, since it may changed due to factors outside the control of the program e.g.
- hardware registers
- memory-mapped I/O
- other types of memory-mapped hardware
// if not using the word volatile, the compiler may kill the procedure of checking whether the flag is set.
volatile int flag;
void do_something() {
while (!flag) {
// Wait for flag to be set
}
// Do something once flag has been set
}
restrict
pointer is not aliased
-
tells compiler that an object is the only that a pointer can points to
-
compiler will know that the pointer is not aliased.
-
aliased: two pointers pointing to the same object
int x = 0;
int *p1 = &x;
int *p2 = &x;
- tells the compiler to do optimization
- However compiler will not check whether a pointer is aliased or not. You need to ensure that yourself.
void copy_data(int *restrict dst, const int *restrict src, size_t n) {
for (size_t i = 0; i < n; i++) {
dst[i] = src[i];
}
}
Declarators
// an array of 10 pointers
int *ap[10];
// an array of pointers to function taking nothing returning pointer to int
int *(*x[10])(void);
// an pointer to function taking int returning nothing
void (*pf)(int val);
Inline Functions
- Normal Function
- jump to the first instruction in the function
- the overhead may be huge
C can’t
- return arrays
- return functions
- return array of functions