Take the 2-minute tour ×
Arduino Stack Exchange is a question and answer site for developers of open-source hardware and software that is compatible with Arduino. It's 100% free, no registration required.

These are two ways I can hold a variable outside of loop (or any function).

First, I can declare it with global scope outside of loop:

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

int count = 0;

void loop()
{
    Serial.println(count);
    count++;

    delay(250);
}

I can also declare it static inside the loop:

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

void loop()
{
    static int count = 0;

    Serial.println(count);
    count++;

    delay(250);
}

What difference, if any, will this make?

share|improve this question

4 Answers 4

up vote 7 down vote accepted

The most basic difference is of scope.

In the first case, you are declaring a global variable. It is a variable that is accessible in every scope after its definition.

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

void inc();
int count = 0;

void loop()
{
    Serial.println(count);
    count++;

    inc();

    delay(500);
}

void inc() //Can edit the value of count
{
  count=count+1;
};

In the second case, you are declaring a static variable with local scope. The variable will persist for the entire program run similar to global variables, but will be accessible only in the code block it is declared in. This is the same example, with only one change. count is now declared as a static variable inside loop.

void inc();

void loop()
{
    static int count = 0;
    Serial.println(count);
    count++;

    inc();

    delay(500);
}

This will not compile as the function inc() does not have access to count.

Global variables, however seemingly useful, come with some pitfalls. These can even cause damage when it comes to writing programs that can interact with the physical surroundings. This a very basic example of something that is quite likely to happen, as soon as programs start getting larger. A function may inadvertently change the state of a global variable.

void setup()
{
    Serial.begin(9600);
}
void another_function();
int state=0;

void loop()
{
    //Keep toggling the state
    Serial.println(state);
    delay(250);
    state=state?0:1;

    //Some unrelated function call
    another_function();
}

void another_function()
{
  //Inadvertently changes state
  state=1;

}

Such cases are very hard to debug. This type of problem however, can easily be detected, by simply using a static variable.

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

void loop()
{
    static int state=0;

    //Keep toggling the state
    Serial.println(state);
    delay(250);
    state=state?0:1;

    //Some unrelated function call
    another_function();
}

void another_function()
{
  //Results in a compile time error. Saves time.
  state=1;

}
share|improve this answer

From a functional perspective, both versions generate the same result, since in both cases the value of count is stored between the executions of the loop() (either because it is a global variable or because it is marked as static and therefore keeps its value).

So the decision which to choose come down to following arguments:

  1. Generally, in computer science, it is encouraged to keep your variables as local as possible in terms of scope. This usually results in much clearer code with less side-effects and reduces chances of someone else using that global variable screwing up your logic). E.g. in your first example, other logic areas might change the count value, whereas in the second, only that particular function loop()can do so).
  2. Global and static variables always occupy memory, where as locals only do when they are in scope. In your above examples that makes no difference (since in one you use a global, in the other a static variable), but in bigger and more complex programs it might and you could save memory using non-static locals. However: If you have a variable in a logic area that is executed very often, consider making it either static or global, since otherwise you loose a tiny bit of performance each time that logic area is entered, since it takes a bit of time to allocate the memory for that new variable instance. You need to find a balance between memory load and performance.
  3. Other points such as better layout for static analysis or optimization by the compiler might also come into play.
  4. In some special scenarios, there might be issues with the unpredictable initialization order of static elements (not sure about that point, compare this link though).

Source: Similar thread on arduino.cc

share|improve this answer
    
Re-entrancy should never be an issue on Arduino since it doesn't support concurrency. –  Peter R. Bloomfield Mar 1 at 11:12
    
True. That was more of a general point, but indeed not relevant for Arduino. I removed that bit. –  Philip Allgaier Mar 1 at 11:17
1  
A static variable declared inside a scope will always exist and use the same space as a global variable! In the OP code, the only difference is what code can access the variable. In scipe static wil be accessible within the same scope. –  jfpoilpret Mar 1 at 12:39
1  
@jfpoilpret That of course is true, and I see that the respective part in my answer was a bit misleading. Fixed that. –  Philip Allgaier Mar 1 at 18:39

Both variables are static - they persist for the entire execution session. The global is visible to any function if it declares - not defines - the global, or if the function follows the definition in the same compilation unit (file + includes).

Moving the definition of count to inside of a function both limits its scope of visibility to the nearest enclosing set of {}es, and gives it function invocation lifetime (it is created and destroyed as the function is entered and exited). Declaring it static as well gives it execution session lifetime it exists from the start to the end of the execution session, persisting across function invocations.

BTW: be cautious about using initialized statics within a function, as I have seen some versions of the gnu compiler get this wrong. An automatic variable with an initializer should be created and initialized on every function entry. A static with an initializer should only be initialized once, during the execution setup, before main() is given control (just as a global would be). I have had local statics get reinitialized on each function entry as though they were automatics, which is incorrect. Test your own compiler to be sure.

share|improve this answer
    
I'm not sure I understand what you mean about a function declaring a global. Do you mean as an extern? –  Peter R. Bloomfield Mar 2 at 22:43
    
@PeterR.Bloomfield: I'm not sure what part of my post your asking about, but I was referring to the OP's two examples - the first, an inherently global definition and the second, a local static. –  JRobert Mar 2 at 22:59

According to Atmel's documentation: "If a global variable is declared, a unique address in the SRAM will be assigned to this variable at program link time."

The complete documetation is here (Tip #2 for global variables): http://www.atmel.com/images/doc8453.pdf

share|improve this answer
4  
Aren't both examples going to end up with a unique address in SRAM? They both need to persist. –  Cybergibbons Mar 1 at 10:43
2  
Yes actually you can find that info in the same document in tip #6 –  jfpoilpret Mar 1 at 14:04

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.