Key Points
- Static variables in C preserve their value even when out of scope, allowing for efficient memory management and reuse between function calls.
- Static variables can be local or global, with local static variables declared inside a function and global static variables declared outside of a function.
- Using static variables can help with encapsulation, as they can hide data from other files when declared with file scope.
- Thread safety concerns arise with static variables, as multiple threads can access the same variable without proper synchronization.
- To reduce thread safety issues, synchronization techniques like mutex and atomic operations can be used.
When we declare variables in C, they typically reside within a specific code block or function definition. Once the function has been called and the code executed, the program usually frees up the memory that was allocated for the variable. However, sometimes we want to share these variables among multiple functions within the same program. This is where static variables can be useful. By using static variables, we can preserve values after a function has been called. In this article, we’re going to explore how static variables in C work, how to declare and define them and their benefits and drawbacks, with examples.
What Is a Static Variable?
Static variables work by preserving their value even once they’re out of scope. By scope, we mean the area of a program where the variable is accessible. Generally, there are three kinds of scope – function, file, and block. Variables usually have block or function scope, meaning they’re no longer available once that particular function has been called, or that block executed. If we need to use them again, we must initialize them with new values. It’s also difficult to use multiple functions with the same variable. Therefore, when we want to reuse a variable and not have to initialize it several times, static variables are a good option to use.
What Other Types of Variables Are There?
Static variables are in contrast to automatic variables, which are the default type of variable in C. The program automatically creates automatic variables when a function is called, and memory is deallocated once the function call is over. In addition to automatic, we can also have register, external, volatile, and constant variables. A brief description of these follows.
- Register variables – These are usually limited to function scope and are used to suggest how to store a variable to the compiler. However, they’re not mandatory and are sometimes ignored by the compiler.
- External variables – We also know these as global variables, meaning they’re declared outside of functions and have file scope properties. They’re similar to static variables in that they have file scope, but global variables can’t have function scope.
- Volatile variables – This kind of variable is used to indicate to the compiler that its value may unexpectedly change, such as due to interrupts from the hardware. The compiler doesn’t optimize these variables, but reads their values from memory instead.
- Constant variables – Using the “const” keyword, we can declare constant variables, which can’t be modified after we have initialized them. Subsequently, they’re mainly used to define constants that we don’t want to change during runtime.
What’s the Difference Between Local and Global Static Variables?
We briefly discussed global variables and their differences to static variables. However, you can actually have global static variables and local static variables. If we declare a static variable outside of a function, then it becomes a static global variable. We can access this throughout the entire program. On the other hand, if we declare it inside a function, it’s known as a static local variable. This will behave similarly to an automatic local variable, but will have its memory available throughout execution and between function calls.
How Are Static Variables Declared and Defined?
To declare a static variable, we simply use the “static” keyword. We can use this with both functions and variables. The general syntax for declaring a static variable is as follows:
static type_of_data name_of_variable = variable_value
Where “static” is the keyword, “type_of_data” is the data type (e.g. float, int, char), “name_of_variable” is the name we give to the variable, and “variable_value” is the value we’ve initialized the variable with. Note that if we don’t provide a value, the program will initialize the variable with 0 by default.
Examples of Static Variables
Now it’s time to illustrate how we can use the various types of static variables in C. First, let’s look at static local variables.
Local Variable Example
To understand how to implement a static local variable, take a look at this code:
#include <stdio.h>
void increment() {
static int counter = 0;
counter++;
printf("Counter: %dn", counter);
}
int main() {
increment();
increment();
increment();
return 0;
}
To start, we’ve defined the “increment()” function and indicated the return type is “void”, meaning it doesn’t return any value.
Next, we declare the static local variable “counter”, of the “int” type, and initialized it to 0.
The line following this indicates that the program increments the counter variable by 1. Every time we call the increment function, the program retains the variable.
It prints the values as per the “printf()” function. We use “%d” to specify the integer format, and “n” to print a newline between each result.
We then call the “main()” function, which returns a value of the int type. The program increments the variable three times and then prints the results to the console. You can see the output in the image below.

©History-Computer.com
Global Variable Example
As mentioned, we can access global variables outside of a function. But we can only access static global variables from within the file in which we’ve declared them. This helps to enforce encapsulation, as the data is hidden from external files. To illustrate, consider this code block:
#include <stdio.h>
static int globalVariable = 10;
void incrementGlobal() {
globalVariable++;
}
int main() {
printf("Initial value: %dn", globalVariable);
incrementGlobal();
printf("After increment: %dn", globalVariable);
incrementGlobal();
printf("After increment again: %dn", globalVariable);
return 0;
}
This is similar to the previous example, but because we’re using a static global variable, we have declared the vaiable at the top, outside of the function. We have initialized it to 10.
After this, we define the “incrementGlobal()” function, which increments our global variable by 1 each time the program calls it.
Finally, we define the “main()” function, incrementing the variable twice and printing each result. As before, you can see the output in the image below.

©History-Computer.com
Pros, Cons, and Applications of Static Variables in C
While static variables can help make code more reusable, they also have their potential drawbacks. We have summarized the pros and cons of static variables in the table below.
Pros | Cons |
---|---|
Useful for implementing accumulators and counters, as they can be accessed by multiple functions | Thread safety concerns. Multiple threads can potentially access the same variable, and may not be properly synchronized in their operations. |
Preserve data values between function calls, which helps make memory usage efficient | Global variables can complicate code, as multiple functions can access them. |
Useful for encapsulation, as static variables with file scope can hide data from other files. | If static variables aren’t being used, they still occupy memory during program execution. |
We can initialize variables with a specific value irrespective of how many times functions are called on them. | Testing functionality can become difficult, as static variables may introduce hidden dependencies. |
Best Practices
We’ve covered the pros and cons of static variables, so it makes sense to describe how to best use them. To help reduce thread safety issues, we can use synchronization techniques to limit the concurrent access of variables. Two of the most common tools are mutex and atomic operations.
Mutex, or mutual exclusion, permits only one thread to access the variable. They use a mutex lock, which the thread tries to acquire. But if another thread is already accessing this lock, the program will suspend the request.
Atomic operations, on the other hand, don’t require the use of a lock. They guarantee that the program can complete an operation without any interruption by other threads, i.e., atomically. Common atomic operations include read-modify-write, where the program updates the variable and overwrites its value, and load-and-store, where the program loads a value from memory and stores it in a register while it is updating it. Note that load-and-store isn’t atomic by itself, so we must use it together with other synchronization methods, such as mutexes.
Applications of Static Variables in C
We know so far that static variables are useful for implementing functions like counters and accumulators, and for preserving values between function calls. However, they have some other uses as well. We can also use them to cache data that are memory-intensive or frequently used, which helps to eliminate the need for unnecessary computations. Further, we can use static variables to control certain behaviors, since they preserve variable values between function calls. This can allow us to check whether the program has performed a certain action yet.
Wrapping Up
In summary, static variables in C have many perks that automatic variables don’t. They can preserve values between function calls, which helps to make memory management more efficient and which we can use to let the program remember the state of a variable. We also use static variables to implement tracking functions and counters, as well as caching expensive data. They differ from automatic variables because they can have function or file scope, and also from global variables since they’re only accessible within the same file. This helps to enforce encapsulation through data hiding. As long as you plan to address thread safety concerns and don’t leave unused static variables in your code, you can gain many advantages from static variables that other variable types can’t offer.
The image featured at the top of this post is ©Media Whale Stock/Shutterstock.com.