Lifetime of the variable usually starts when the block is executed and the variable is declared, and ends when the block is finished. But, if the variable is static, the lifetime(or retaining value) would be throughout the program though it's scope is finished.
Scope/Visibility/Accessibility of the variable is where ever the variables can be accessed.
There are four main scopes(visibility/accessibility):
- Function Scope
- Block/Local Scope i.e ({ and )}
- File Scope
- Program Scope
Static Variables
- Static variables are initialized to 0 by default if not initialized explicitly. These can be initialized using only constant literals, so we can't use the return value of any function.
#include<stdio.h> int function(void) { return 73; } int main() { static int i = function(); printf(" value of i = %d", i); return 0; }
- Static variable preserves its value (lifetime of the variable is throughout the program) even after it is out of its scope. It remains in memory while the program is running. It basically used to count the number of times program/counter increments throughout the program.
- Static variables are allocated memory in the data segment. Click here to know the memory layout of the process.
- Static variables shouldn't be declared inside the structure because C compiler expects structure elements to be placed together as the value of the structure elements retrieved by counting the offset from the beginning of the structure, so all structure elements should be placed in the same memory segment.
Function/Block Scope
#include<stdio.h> #define NUMBER_OF_FUNC_CALLS 3 int fun() { static int count = 0; count++; return count; } int main() { int i; for (i = 0; i < NUMBER_OF_FUNC_CALLS; i++) { printf("%d ", fun()); } return 0; }
Output:
1 2 3
|
#include<stdio.h> #define NUMBER_OF_FUNC_CALLS 3 void fun() { static int count = 0; count++; printf(" In local fun() count is %d\n", count); return; } int main() { int i; for (i = 0; i < NUMBER_OF_FUNC_CALLS; i++) { fun(); printf(" In main count is %d\n", count); } return 0; }
#include<stdio.h> #define NUMBER_OF_FUNC_CALLS 3 void fun() { static int count = 0; count++; printf(" In local fun() count is %d\n", count); return; } int main() { int i; for (i = 0; i < NUMBER_OF_FUNC_CALLS; i++) { fun(); } return 0; }
Nested Block Scope
File Scope
#include <stdio.h> #include "tree.h" int main() { int iterator; for (iterator = 0; iterator < NO_ITERATOR; iterator++) { counter++; } printf("In main counter value %d", counter); return 0; }
tree.h#ifndef TREE_H #define TREE_H #define NO_ITERATOR 5 static int counter = 0; #endif
#ifndef TREE_H #define TREE_H #define NO_ITERATOR 5 static int counter = 0; #endif
main.c
#include <stdio.h> #include "tree.h" int main() { int iterator; for (iterator = 0; iterator < NO_ITERATOR; iterator++) { counter++; } printf("In main.c counter value %d", counter); function(); return 0; }
#include <stdio.h> #include "tree.h" int function() { printf("In file1.c counter value %d", counter); return 0; }
In example 2, the static variable counter can be accessible in different .c files as it is declared and defined in the tree.h file. The value of the variable is limited/accessible to that particular .c file since it is static. It can't retain the value "5" to the other file1.c file though its lifetime is throughout the program. Here, the static is defined in multiple .c files. Here, both main.c & file1.c has its own copy of variable counter.
Avoid including global static variables more than one .c file and avoid expecting the value will be retained in other .c files. In this case, use global variables where the values will be retained in all .c files. See example 5 in extern variables.
#ifndef TREE_H #define TREE_H #define NO_ITERATOR 5 static int counter = 0; #endif
#include <stdio.h> #include "tree.h" int main() { int iterator; for (iterator = 0; iterator < NO_ITERATOR; iterator++) { counter++; } printf("In main.c counter value %d", counter); function(); return 0; }
file1.c
Static Functions
a.c ------ #include <stdio.h> /* Undefined behavior: already defined in main. * Binutils 2.24 gives an error and refuses to link. * https://stackoverflow.com/questions/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c */ /*void f() { puts("a f"); }*/ /* OK: only declared, not defined. Will use the one in main. */ void f(void); /* OK: only visible to this file. */ static void sf() { puts("a sf"); } void a() { f(); sf(); }
main.c ------- #include <stdio.h> void a(void); void f() { puts("main f"); } static void sf() { puts("main sf"); } void m() { f(); sf(); } int main() { m(); a(); return 0; }
Compile and run: ----------------- gcc -c a.c -o a.o gcc -c main.c -o main.o gcc -o main main.o a.o ./main Output: ------- main f main sf main f a sf
Extern Variables
int count;
The above is the declaration and definition of a variable, and it means memory is allocated for variable "count". But, if we prepend extern with C variables, the memory will not be allocated, these variables will only be declared.
extern int count;
Now, we can answer if someone asks how would you declare a variable without defining it. Ok! Let's go to our topic. Extern keyword extends the visibility of the program.
Note: The variable can be declared at any number of time.
Definition
Extern can be shared between modules, and it is linkage modifier.
Example 1
main.c#include<stdio.h> int count; void main() { count = 5; printf("Function %s Line %d Count %d\n", __func__, __LINE__, count); return; }
Output:
Function main Line 7 Count 5
|
Here, the count is defined and declared implicitly globally.
Example 2
main.c#include<stdio.h> extern int count; void main() { count = 5; printf("Function %s Line %d Count %d\n", __func__, __LINE__, count); return; }
Output:
"count" is not defined but declared, it throws the error because the memory is not allocated, but it tries to change the value.
Example 3
main.c#include<stdio.h> #include "count.h" int count; void main() { count = 5; printf("Function %s Line %d Count %d\n", __func__, __LINE__, count); return; }
count.h
#ifndef _COUNT_H #define _COUNT_H extern int count; #endif
Output:
Function main Line 7 Count 5
|
Example 4
main.c#include<stdio.h> extern int count = 6; void main() { printf("Function %s Line %d Count %d\n", __func__, __LINE__, count); return; }
Output:
Function main Line 8 Count 6
|
Here comes the surprise, though extern is prepended in the variable, it can be defined or the memory can be allocated as well if it is initialized.
The above program might throw a warning as " 'count' initialized and declared 'extern' [enabled by default]"
Example 5
#include<stdio.h> extern int count; void main() { printf("Function %s Line %d Count %d\n", __func__, __LINE__, count); count_function(); printf("Function %s Line %d Count %d\n", __func__, __LINE__, count); return; }
count.c
#include<stdio.h> int count = 0; void count_function() { int i; for (i = 0; i < 5; i ++) { count++; } printf("Function %s Line %d Count %d\n", __func__, __LINE__, count); return; }
Output:
Function main Line 14 count 0
Function count_function Line 10 count 5
Function main Line 16 count 5
|
Variables can be prepended with extern in the .h files which is included in many .c files if you want to use the variable in multiple files.
Please be cautious not to add extern variables/functions in .c files. Always use extern in .h files.
Example 6 (Must Read *)
head.h -------- #ifndef _HEAD_ #define _HEAD_ int count = 0; void file_two(); #endif file1.c -------- #include <stdio.h> #include "head.h" int main() { printf("main count %d \n", count); file_two(); return 0; } file2.c -------- #include <stdio.h> #include "head.h" void file_two() { printf("file two count %d \n", count); return; }
|
Here, it says it finds duplicate definition for the count.
Example 7 (Must Read *)
head.h -------- #ifndef _HEAD_ #define _HEAD_ extern int count = 0; void file_two(); #endif file1.c -------- #include <stdio.h> #include "head.h" int main() { printf("main count %d \n", count); file_two(); return 0; } file2.c -------- #include <stdio.h> #include "head.h" void file_two() { printf("file two count %d \n", count); return; }
|
Example 7 (Must Read *)
head.h -------- #ifndef _HEAD_ #define _HEAD_ extern int count; void file_two(); #endif file1.c -------- #include <stdio.h> #include "head.h" int main() { printf("main count %d \n", count); file_two(); return 0; } file2.c -------- #include <stdio.h> #include "head.h" void file_two() { printf("file two count %d \n", count); return; }
Example 8 (Must Read *)
head.h -------- #ifndef _HEAD_ #define _HEAD_ extern int count; void file_two(); #endif file1.c -------- #include <stdio.h> #include "head.h" int count = 1; int main() { printf("main count %d \n", count); count++; file_two(); return 0; } file2.c -------- #include <stdio.h> #include "head.h" void file_two() { cunt = 90; printf("file two count %d \n", count); return; }
Good..keep post with maximum examples.
ReplyDeleteThank you!!!
Sure. Thank you!!
Delete