Arduino programming guide series

21

What is a "static" variable and how to use it

The C language contains special keywords that modify the way a variable behaves. One of them is the keyword "static". The way it works is not obvious, so I have created a series of experiments to help you understand.

A static variable is used to preserve the value of a variable. When you mark a variable as static, its value is preserved in your program until the program ends.

Think of a static variable as if it was global, with a reduced scope. A global variable has global scope, and it is preserved for as long as the program runs. A static variable has local scope, but is also preserved for as long as the program runs.

You would normally use a static variable in cases where you wish to preserve the value of a variable inside a function. Normal local variables are destroyed when the function completes and recreated/instantiated when the function is called.

Let's use an example to help understand the behavior of a static variable.

Consider this code, "sample A", which you can get from Github:

Upload the sketch to your Arduino and open the serial monitor. The monitor will show this output:

In a_function: 0
In a_function: 0
In a_function: 0
In a_function: 0
In a_function: 0
In a_function: 0
In a_function: 0
In a_function: 0

The counter remains "0" because each time the a_fuction is called, the local variable local_variable is re-declared and re-initialized to "0". Even though in line 16, the value of the local variable is incremented by one, the new value is lost.

Now consider this code, "sample B", which you can get from Github:

Upload the sketch to your Arduino and open the serial monitor. The monitor will show this output:

In a_function: 0
In loop: 1
In a_function: 1
In loop: 2
In a_function: 2
In loop: 3
In a_function: 3
In loop: 4
In a_function: 4
In loop: 5
In a_function: 5
In loop: 6
In a_function: 6
In loop: 7
In a_function: 7
In loop: 8
In a_function: 8
In loop: 9
In a_function: 9
In loop: 10

In this variation of the sketch, the variable local_variable is made global by defining it and initializing it in line 1. Even though this is a global variable, I decided to keep the original name in order to maintain continuity between the examples.

Because the value of the local_variable is incremented inside the a_function, and not re-initialized (as it did in the original  version of the sketch), the value is not lost. It is preserved during the subsequent calls of the a_function function.

Now, consider the next variation of the code, "sample C", which you can get from Github:

Upload the sketch to your Arduino and open the serial monitor. The monitor will show this output:

In a_function: 0
In loop: 1
In a_function: 1
In loop: 2
In a_function: 2
In loop: 3
In a_function: 3
In loop: 4
In a_function: 4
In loop: 5
In a_function: 5
In loop: 6
In a_function: 6
In loop: 7
In a_function: 7
In loop: 8
In a_function: 8
In loop: 9
In a_function: 9
In loop: 10

The only difference between the sketches of variation B and C is that in C, the variable local_variable is marked as static.

The output of the two sketches is identical.

Finally, consider the last variation of the code, "sample D", which you can get from Github

Upload the sketch to your Arduino and open the serial monitor. The monitor will show this output:

In a_function: 0
In a_function: 1
In a_function: 2
In a_function: 3
In a_function: 4
In a_function: 5
In a_function: 6
In a_function: 7
In a_function: 8
In a_function: 9
In a_function: 10

Isn't this interesting?

In Sample D, the local_variable variable is marked as static, but this time is declared inside the a_function function. As per the first experiment, you would expect the the serial monitor will show zeros as the variable is re-initialized in line 13.

But it doesn't.

Because local_variable is marked as static, its value is preserved when the function finishes its execution. It is not re-initialized when the same function is called again.

When will the contents of the static variable dissapear? When the program ends, just like it happens for a global variable.

Let's recap the outcome of these experiments.

In sample A, the monitor printout shows that the variable is always 0. We expected that since the variable is defined and initialized inside the function. Every time the function is called in the loop, the variable is re-defined and initialized to 0.

In sample B, the variable local_variable is global. As expected, both the loop and a_function functions have access to it. Once it initialized, it increments by 1 inside a_function, and the same value is printed to the monitor from inside loop and a_function.

In sample C, we marked local_variable as static, and due to its position, it is still globally accessible. The printout we get is identical to the one we got from sample B. Declaring this global variable as static has no effect on the outcome. The compiler can even ignore this modifier.

Finally, in sample D, we move the declaration of the variable inside the a_function function. At this point, the sketch is identical to that of sample A. But in sample D, we use the static modifier. The printout from the serial monitor shows that the value of the variable is preserved between calls of a_function.

What is the practical lesson of all this?

1. If you want to preserve the state of a variable across a program, you can create it as a global variable. Marking it as static does not change the fact that the value of the variable will be preserved for the life of the program. However, a global variable can be accessed anywhere in the program, and this could cause defects. In large programs, and because most Arduino hobbyists don’t have access to a debugger, it is best to not use a global variable unless access to it is truly globally required.


2. If you want to preserve the state of a function local variable, mark it as static. You will get all the benefits of the globally declared variable, without the problem described in point 1.

"Arduino programming" series

New to the Arduino?

Arduino Step by Step Getting Started is our most popular course for beginners.

This course is packed with high-quality video, mini-projects, and everything you need to learn Arduino from the ground up. We'll help you get started and at every step with top-notch instruction and our super-helpful course discussion space.

Tech Explorations Arduino intermediate level

Done with the basics? Looking for more advanced topics?

Arduino Step by Step Getting Serious is our comprehensive Arduino course for people ready to go to the next level.

Learn about Wifi, BLE and radio, motors (servo, DC and stepper motors with various controllers), LCD, OLED and TFT screens with buttons and touch interfaces, control large loads like relays and lights, and much much MUCH more.


>