Static variable in C

You might often hear the same questions from your peers or colleagues and you try to explain them your understanding of the subject/problem but have second thoughts in your mind, so you go back to the basics again just to confirm that you are correct.

Static keyword in C language is perfect example of that type. This keyword is part of the storage class types in C. Static storage class can be assigned to a function or to a variable.

Basics

By default, the scope of functions in C are global and scope of the variables depend upon the storage class & where the variable has been declared/defined/initialised. If a variable is declared inside a function without using any specific storage class then they belong to the auto storage class and memory is allocated for them in the stack. Since the memory is allocated for them in the stack as soon as the function returns, the contents of the memory are lost. In short the local variable (that’s the way we call auto variables) is freed as soon as the function exits.

Static

But when static keyword is used to declare a variable inside a function then everything changes. First and the most important thing is that the memory that is allocated for this variable is not in the stack but in the data section. So the memory is preserved through out the execution of the program. And also if no value is assigned to the variable then it is initialised to zero (we shall see in an example below).

The above said scenario is true for variables declared inside a function.

What if we declare variables outside of any function. Now the scope of these variables are global. What does that actually mean ? Is it available to the set of files which is going to be linked with this file or is it available only to the current file ?

The answer is simple, it is going to the available to the set of files with which it is linked.

Real deal

Enough with the theory, let us see what is actually happening and discuss more. Below is a simple C code and it is named as static.c. Below is the content of the file:

 

#include <stdio.h>
int global_vari;
static int global_static_vari;
main()
{
foo();
return 0;
}
foo()
{
int local_vari;
static int local_static_vari;
}

Let us compile the code with the below command:

root@kasi:~# gcc -o static static.c

As seen above we have declared two variables outside of any function including the main function,  “global_vari” & “global_static_vari” (type static). And we have a function by the name foo and it has two variables “local_vari” & “local_static_vari” (type static). (As mentioned above) by default variables declared outside any function have a global scope in C and if they are initialised i.e if they are assigned any value then they are stored in the data section of the ELF else they are stored in the bss section of the ELF. In the above code,  “global_vari” & “global_static_vari” are both stored in bss section.

With nm tool we can see the symbol table of an ELF file.

root@kasi:~# nm static

Isolated contents of “global_vari” & “global_static_vari” from the nm tool are shown below.

0000000000601038 b global_static_vari

0000000000601040 B global_vari

Both these variables have letter b and B mapped to them respectively which means they belong to the bss section of the ELF file. More preciously “global_vari” which is uninitialised, has global scope, and marked with letter B is mapped to bss section and available outside the current file whereas “global_static_vari” declared with static keyword which is also uninitialised and marked with letter b is mapped to bss section and is available only to the current file.

NM tool

This tool helps us to read the symbols available in a ELF file. This is much helpful for debugging purposes during the development stage of a project. An ELF file is a collection of various sections like text, data, bss, init, rodata etc. They are marked with alphabets like T for text section, D for data section and many more (man nm). Both small and capital letters are used for mapping purposes and the difference between capital letters and small letters is that sections marked with capital letters are available outside the current file whereas sections marked to lower case letters are available to the current file alone.

For example, initialised variables with global scope are marked with capital letter D whereas initialised variables with static storage class with local scope are marked with small letter d. Same is true for functions also. Functions without static keyword are marked with capital letter T and functions with static keyword are marked with capital letter t. We shall see this with an actual example below.

The above brief will help you to understand when you see both capital and small letters used in the ELF file as it will be confusing initially.

Variables inside function

Now if we look the variables inside the function

foo()
{
int local_vari;
static int local_static_vari;
}

local_vari” belongs to the auto storage class as it is declared without specifying any storage class and it is also not initialised. Auto storage class is the default storage class used in C. Variables declared without any storage class prefix belong to the storage class of this type. (As we all know) variables declared inside a function without any specific storage class are allocated memory in the stack (at runtime). The value of the variable could be anything ( called as garbage value). More technically the contents of the memory location allocated for that variable could be anything. If you run this program more than once and try to print the value of “local_vari“, each time you will get a different value. This is because the memory for this variable is allocated during the execution of the program only i.e only at run-time and not at compile time. “local_vari” wont be available in the symbol table which can be verified using the nm tool.

And speaking of “local_static_vari” variable which is declared with static prefix is allocated memory in the bss section and initialised with zero. As discussed above the static variables have a local scope and they are available only to the current file.We can confirm this using the nm tool again.

000000000060103c b local_static_vari.2293

The value of the static variable remains preserved between different function invocations. Let us see with a simple example using the same code what it actually means. We can modify the main function to call foo function few more times and increment the value of “local_static_vari” each time we call it.

#include <stdio.h>
int global_vari;
static int global_static_vari;
main()
{
foo();
foo();
foo();
return 0;
}
foo()
{
int local_vari;
static int local_static_vari;
printf("local_static_vari is %d\n", local_static_vari); /* Print before incrementing */
local_static_vari++;
}

Below is the output when the above code is compiled and run.

local_static_vari is 0

local_static_vari is 1

local_static_vari is 2

When foo function is called the first time, first print output goes to show that the “local_static_vari” has a value of zero. This call returns and we again call foo function from main function. The second print now prints the value of “local_static_vari” as one since we have incremented it in the previous invocation of foo. When foo function is called the third time from the main function “local_static_vari” is incremented by one again and it now becomes two and that is the output of the third print. It shows that the values stored by static variables are preserved across function call’s. Foo could be called from any other function and still the value of “local_static_vari” variable will be preserved. You can check this by simply defining a new function and by calling foo from there.

Finally to summarise the topic:

  • Static variable inside a function preserves its value between multiple invocations.
  • Static global variable or a function is visible only in the file it’s declared in and are not visible outside of the C file.

Pls note, the machine in which the above code was compiled was a 64-bit machine so the addresses of the variables are shown in 64-bit format.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s