bclose

56 – VARIABLE SCOPE IN ARDUINO

Objectives

 

 

    • Introduce the concept of variable scope.
    • Show why do we need the variable scope.
    • Global and local variables.
    • Static variables.

 

 

BILL OF MATERIALS

Arduino UNO

 Arduino UNO or equivalent.

 

Variables

 

In the introduction to Arduino tutorials, we have been dealing with variables in a more or less informal way, by a deliberate decision. We have used different types of variables and we have dealing with them, without going into much detail.

Specifically we have used local and global variables, but avoiding discreetly commenting on the matter. However it is time to go into detail in a key property of C ++ variables (and in almost any modern programming language), called variable scope and persistence.

To understand the concept of variable scope, we should take a short detour and talk about computing history (keep calm, it will be a very short story). Historically, in the early programming languages, all variables were global variables. This means that when defined, its value was accessible from anywhere in the program. Its value could be read or modified without restrictions.

At first, it may seem ideal. But as programs grow in size and complexity, things get complicated and tends to generate problems hard to detect or solve.

For example, during the introductory course chapters we have used endlessly variables such as i, j in the for loops, for example. As a program has half a dozen loops, and we usually use these variable names to perform the iteration, it is just a matter of time (little time, believe me) that the variable of a loop, get confused or mixed up with another variable that has the same name in a different loop.

Suddenly the program starts acting erratically, due to a variable in a program area, that we suppose is under control, that takes different values than the expected because we use a variable with the same name in another area without noticing it.

Establish the relationship between the confusion of names and the strange problems that appear, can be much less evident in the real life of what appears now in an ad hoc example, and as the program grows the problem tends to grow into infinity.

Therefore, it was proposed a very elegant solution (which are the ones we like), that is, that variables were not visible in the whole program scope, but only in certain areas, according to strict rules.

As C ++ requires that variables must be declared before use, variables that are declared outside a block of code are called Global variables, being available from anywhere in a program.

 
  • We have talked in previous chapters about the concept of block of code as that group of instructions contained between braces (opening and closing braces).
 

The variables declared within a block of code are called local variables, and they only exist within the block where they are defined and not outside. When our program enters the block, the variable is declared and created on the fly for internal use.

When the program leaves the block, the local variable is destroyed and disappears into oblivion. The next time we return to the block it will be created again, without remembering if it had had a previous existence.

This way, when we need to define variables to perform a for loop, for example, ad hoc variables are created and destroyed when leaving, preventing a local variable to get confused with another local variable of another block of code.

Simply there do not exist external variables to the block, except the global variables, and therefore, although we use the same variable names, they can’t cause unforeseen errors.

We solve the problem in one fell swoop and definitively. Smart, isn’t it?

Let’s see some examples.

 

EXAMPLES OF GLOBAL AND LOCAL VARIABLES

 

I recommend you not only reading the examples. Download the sketch into your Arduino and test it, because the issue is more delicate than it seems and it is not easy to get used to the idea.

We will use a global variable called control to prevent the result from repeating in the console. To define a global variable, simply declare it outside a block. At first it’s okay

bool control = true;

void setup()
  {        Serial.begin(9600);   }

void loop()
   {   int j = 3 ;
       if ( control)
            {  for (j=0 ; j<10 ;j++)
                  {    Serial.print("j = ");
                       Serial.println(j);
                  }
               Serial.println("...........................");
               Serial.println(j);
            }
       control = false ;   // Not to print the result again
   }

Think for a moment before seeing the result. Which do you think it will be?

Notice that we define the variable j at the beginning of the loop, although we do not define it again inside the for loop but we use a pre-existing variable.

So the for loop assumes that you want to use a pre-declared variable and uses it for the iteration.

Chapter 72, sketch 1

The result is 10, naturally. Let’s make a slight modification of the previous sketch. Let’s re-declare the variable j as an int, but within the for loop.

void loop()
   {   int j = 3 ;
       if ( control)
            {  for (int j=0 ; j<10 ;j++)     // Pay attention here
                  {    Serial.print("j = ");
                       Serial.println(j);
                  }
               Serial.println("...........................");
               Serial.println(j);
            }
       control = false ;   // Not to print the result again
   }

This time, the result changes radically:

Chapter 72, Sketch 2

 

The last line is 3. The first j variable inside the loop function is different from the variable j inside the for loop, because we have defined it in a separate block. So when the local variable j leaves the for loop, it vanishes and only remains the value of the global variable j (the first one), that’s why the result after the dotted line is 3 and not 10, as in the previous example.

 
  • In the for statement, and in any other that is applied to a block of code, the definitions made are considered to fall within that affected block and not outside.
  • A variable can be declared only once within a block. Any attempt to declare the same variable for the second time, would cause an devastating compiler error:
 
Chapter 72, Sketch 3

 

It is important that you understand that this rule not only has to do with the formal concept of a block of code, as statements contained between opening and closing braces, but it also applies to embedded blocks in which we ignore the braces:

void loop()
   {   int j = 3 ;
       if ( control)
           {   for (int j=0 ; j<10 ;j++)         // Pay attention here
                    Serial.println("j = " + (String)j);
               Serial.println("...........................");
               Serial.println(j);
           }
       control = false ;
   }

The result is the same as before, but now there are no braces in between but an implicit block:

Chapter 72, Sketch 4

All modern programming languages include the concept of local and global variables and apply the rules we have described here (programming languages are based on each other and good ideas are reproduced)

The property of a variable to exist for some time is often called variable persistance.

 

Static Variables

 

This characteristic feature of local variables, that is, their persistence, to be created from nothing and disappear into oblivion after leaving a block of code, is a great advantage and saves developers many hours of wandering in pain through the halls (while they meditate on what the hell is wrong. From here comes their unfair reputation as crazy people).

But sometimes (life is complicated) this may be an inconvenience and we would like some local variables not to disappear when they leave their scope, or at least not to lose their values.

Imagine an Arduino reading data from a sensor and storing its value in a local variable. We would like to know the last value read when we return to that code.

 
  • We can always define a global variable, but it may not make much sense if it is only used inside one function.
 

So, we can define a local variable as static. It means that it will be only accessible from inside this function, but its value will not disappear when it leaves and will persist over time, while the sketch keeps running, retaining its last value.

Let’s see a simple example taken from Wikipedia:

void loop()
   {  if ( control)
         {   Function1(); // step 0
             Function1(); // step 1
             Function1(); // step 2
         }
      control = false ; 
   }
void Function1()
   {  int x = 0;          // We declare x as a local variable
      Serial.println(x);
      x = x + 1;
   }

In the definition of Function1(), we declare x as int, just like that, so the result will be as follows:

Chapter 72, Sketch 5

 

When we are inside Function1(), int x is declared, created on the fly and is assigned the value 0.

Every time we leave Function1(), the variable x vanishes and is re-created the next time we get into it, as befits an obedient local variable. And the process is repeated.

But let’s make a small change and declare the variable x as static inside Function1().

void loop()
   {  
      if ( control)
         {   Function1(); // step 0
             Function1(); // step 1
             Function1(); // step 2
         }
      control = false ; 
   }
void Function1()
   {  
      static int x = 0;          // We declare x as static
      Serial.println(x);
      x = x + 1;
   }

The result is that the variable x does not fade when leaving but retains its value until the next time we return to Function1(). It keeps on being a local variable although it can’t be used by any program or function outside Function1(), but its value does not disappear between consecutive calls, it persists.

Chapter 72, Sketch 6

Note also that as the static variable is not destroyed when leaving, it is created only once and persists indefinitely. The variable declaration and variable assignment is performed only once.

 
  • This means that x is assigned the value 0 once when it is created and not every time you enter the Function1(), as you might initially think. Beware of this!
 

 

SUMMARY

 

 
    • We have seen the differences between global and local variables.
    • The property of the variables that define where they exist and where can be used or not, is known as variable scope.
    • We have seen a few simple examples that show the behavior, somewhat counterintuitive, that derives from the scope definition.
    • We have also seen the concept of static variables as local variables that persist, even when they leave their scope of reference.
 

 

 

 

No Comments

Give a Reply