Skip to content

Scope, Variables, and Parameters

Glenn Salaman edited this page Jan 10, 2021 · 3 revisions

The Basics...

Global Variables

To start, we're going to assume that your program consists of only one file, like an arduino sketch.

Global Variables are defined outside of any function, typically at the top of your file, like this:

#include <Arduino.h>

int global_x = 7;

global_x, in this case, can be accessed and modified anywhere in that file. There can only be one global variable called "global_x"; if you try and define another one, the compiler should give you an error.

The advantage of using global variables is that they are easy...define them once, and you can use them anywhere. The danger is that any function can change them...so you can have a situation like this:

int x;

void count( void )
{
  for (x=0; x<10; x++)
  {
     Serial.println(x);
   }
}

void multiple_counts( void )
{
  for (x=0; x<5; x++)
  {
    Serial.print("Count number: ");
    Serial.println(x);
    count();
  }
}

The theory in this (not-to-useful) snippet is to print the numbers 1-10 (the count function) 5 times (the multiple counts function). But what really happens?

  • On the first iteration through multiple_counts(), we set x to zero, then print Count number: 0, then call count().
  • count() walks through its for-loop as expected, setting x to zero, printing 0, then incrementing x, printing 1, and so on, until x is 10.
  • We then go back to that for-loop in multiple_counts. We're expecting x to be 0 (because that's where it was when we called count()), but it's now 10. 10 is greater than 5, so we jump out of the for loop.

This is only one example of how using globals can yield hard to debug results. While in the above example we could instead make two globals (x1 and x2), there are better ways of doing this, which leads to...

Local Variables

Local variables are defined inside the function where they are used. Whilst some programming languages allow you to define them anywhere, good programming practice tells to define (and comment!!!) them at the top of the function...that way, when someone looking at the code wants to know what this function's locals are, they can find them in one place. That definition looks like this:

void count( void )
{
  int x;  // Counter variable

...
}

Whenever the function count() is called, our program allocates space for a local variable x. This variable can only be used inside of this function, and when the function exits, it goes away.

The advantage here is that I can reuse names...I can have multiple functions, all using the name x as our counter variable. This would look like the following from our example above:

void count( void )
{
  int x;  // counter variable

  for (x=0; x<10; x++)
  {
     Serial.println(x);
   }
}

void multiple_counts( void )
{
  int x;  // counter variable

  for (x=0; x<5; x++)
  {
    Serial.print("Count number: ");
    Serial.println(x);
    count();
  }
}

Now we get the desired behavior.

Function Parameters

Function parameters have the same scope as locals...they can only be used inside of the function. In C, they are passed by VALUE, meaning that when the function is called, the program allocates space for that parameter, and COPIES the value into that parameter. Let's look at this with an example:

void count( int count_to )
{
  int x;  // counter variable

  for (x=0; x<count_to; x++)
  {
     Serial.print(x);
     Serial.print(" ");
   }
   Serial.println();
}

void multiple_counts( void )
{
  int x;  // counter variable

  for (x=0; x<5; x++)
  {
    Serial.print("Count number: ");
    Serial.println(x);
    count(x);
  }
}

We've changed the functionality of our example a little bit...now we want to print 0 , followed by 0 1 , followed by 0 1 2, all the way up to 0 1 2 3 4 .

Let's look a little closer at how these variable and parameters interact throughout the life of our program.

Namespace collisions

Intermediate...

Using Extern

File Static

Function Static

Advanced...

Stack frames