Why are there so many global variables in the examples?

Hello!
I've had two semesters of programming in C for now and I wonder why in the examples stuff with the variables is done so different than we were tought.

So for example in BlinkWithoutDelay (like in nearly every other example) there are many global variables like the ledState, interval, etc.

If I had written this program, I would have stored fpr example the interval with a #define or at least as const long as it is a constant which is not supposed to be changed.
For the ledState I would have chosen a static variable in the loop()-function which should also keep the value.

Is there a specific reasen why the examples are made the way they are?

I think those examples are designed to be as easily understood as possible. Arduino programming is meant to be as accessible as possible to the non-programmer. It is, in some cases, people's first experience with programming of any type, and often their first exposure to C or C++. The examples are designed to appear as simple and approachable as possible, and therefore eschew concerns about efficiency or design scalability.

So there is no specific reason for example not to use static variables in loop()?

This is probably the start of a flame war (which I doubt was your intent.)

The Arduino platform appeals to a large audience. Some people just want to make some kind of flashy blinky project, some people want to build robots, and others are do things nobody ever thought possible.

The examples tend to be simplified to make them more readable than to teach programming concepts. Not everyone who uses an Arduino is (or wants to be) a programmer...

The problem with moving "int ledState = LOW; " or "long previousMillis = 0;" into loop() and making them static is that they would be initialized each time loop() ran. If they were not initialized in loop() they could not be initialized anywhere.

And1G:
So there is no specific reason for example not to use static variables in loop()?

No. Gardner nailed it with the reason why. Many of the examples are improvable from a classical programming point of view. Read the forums a little and you will see many examples of varying levels of coding skill, from cut and paste and experiment, to professional programmers. Arduino is intended to be used by all these levels, but for your own stuff, use the best coding style you can.

The stability that comes from decoupling variables and making them as local as possible is a function of the complexity of the code and the number of people working on the code at the same time.
In a professional programming environment code is worked on by many programmers at the same time. It is imposable to keep track of global variables and prevent one programmer breaking anther's code.

Arduino code tends to be a simple and produced by one person only and so you do not get much of an advantage for the performance hit you take using local variables.

Thank you for your replies!

I've got an other question and I think I might ask it here as it is also about the style of programming:
Is it possible to add own header files and cpp files that can be included in the project with the original Arduino IDE?
I added one header file to the project folder in "sketchbook" but when I do for example #include "header.h" the compiler says the file does not exist...

Once you add the file into the project folder you have to restart the arduino IDE. It will then appear as a tab in the main window. You should then be able to include it and also edit it.

Thanks, restarting the IDE did the trick!

johnwasser:
The problem with moving "int ledState = LOW; " or "long previousMillis = 0;" into loop() and making them static is that they would be initialized each time loop() ran. If they were not initialized in loop() they could not be initialized anywhere.

That is not true. A static function variable will only be initialized the first time the function is called. The compiler will generally generate a "is this initialized?" flag, hidden from your view, to keep track of this. This flag test will happen each time in the function, which is a small performance hit. What's worse is that this test is generally not thread or ISR safe, so if you use a function static from thread or interrupt context, you're asking for trouble.

Explicit globals allow you explicit control of when and how things are initialized. In an embedded system, that explicit control is often a lot more important than the small risk posed by a global being modifiable from a number of different places in the code.

So, this code will print "10, 11, 12, ..." but it will not be as safe or well controlled as a global:

void loop() {
  static unsigned long counter = 10; // only initialized first time
  Serial.println(counter);
  counter++;
}

A static function variable will only be initialized the first time the function is called. The compiler will generally generate a "is this initialized?" flag, hidden from your view, to keep track of this. This flag test will happen each time in the function, which is a small performance hit. What's worse is that this test is generally not thread or ISR safe, so if you use a function static from thread or interrupt context, you're asking for trouble.

I've never heard that before - wouldn't it just be simpler to initialise all the statics and globals just once, before "main" is run?

jwatte:
A static function variable will only be initialized the first time the function is called. The compiler will generally generate a "is this initialized?" flag, hidden from your view, to keep track of this. This flag test will happen each time in the function, which is a small performance hit.

Try this sketch:

class foo
  {
  public:
  foo () { bar = 0; }
  int bar;
  };
  
void setup ()
{
 static foo x;
}

void loop () {}

That generates the errors:

sketch_oct04c.cpp.o: In function `setup':
sketch_oct04c.cpp:13: undefined reference to `__cxa_guard_acquire'
sketch_oct04c.cpp:13: undefined reference to `__cxa_guard_release'

If you move "static foo x;" outside the function the errors go away. So other things being equal, you get different results (ie. errors) if you attempt to declare (some) things statically inside a function.

Nick,
Thats a far cry from the earlier example of using a simple global vs static variable.
I have yet to see a compiler do anything special for initialized data variables as shown
in the earlier example inside the function.
The initialized data is handled in the startup code before main.
So the initial example using counter++ was not really subject to any of the issues mentioned.
(Other than having a reentrancy issue should loop() ever be called from an ISR, which it won't)

--- bill

jwatte:
A static function variable will only be initialized the first time the function is called.

And we can prove that, which is nice.

Given this file "foo.h":

class foo
  {
  public:
  foo ();
  };

And this sketch:

#include "foo.h"

extern "C" {
  __extension__ typedef int __guard __attribute__((mode (__DI__))); 
  int __cxa_guard_acquire(__guard *g) { return !*(char *)(g); };
  void __cxa_guard_release (__guard *g) { *(char *)g = 1; };
  void __cxa_guard_abort (__guard *) { }; 
} // end extern "C"

foo & getFoo ()
{
  static foo x;
  return x;
}  // end of getFoo

// constructor
foo::foo ()
{
  Serial.println ("foo constructed."); 
}  // end of foo::foo

void setup ()
{
  Serial.begin (115200);
  Serial.println ("starting");
  foo & myFoo = getFoo ();
  Serial.println ("foo now exists");
}  // end of setup

void loop () {}

This sketch uses getFoo to avoid the "static member initialization fiasco" - that is, the unpredictable order in which static members are initialized. It avoids it by forcing you to explicitly get a reference to foo, via getFoo, when you need it. However as the debugging shows, foo is not initialized at program startup, but when the first attempt to get it is made.

starting
foo constructed.
foo now exists

And you can see from the generated code that there is indeed a test generated, and depending on the test, foo's constructor at 0xC0 is called:

foo & getFoo ()
{
  static foo x;
  ce:	80 91 3c 01 	lds	r24, 0x013C
  d2:	88 23       	and	r24, r24
  d4:	39 f4       	brne	.+14     	; 0xe4 <_Z6getFoov+0x16>
  d6:	84 e4       	ldi	r24, 0x44	; 68
  d8:	91 e0       	ldi	r25, 0x01	; 1
  da:	0e 94 60 00 	call	0xc0	; 0xc0 <_ZN3fooC1Ev>
void setup ();
void loop ();
extern "C" {
  __extension__ typedef int __guard __attribute__((mode (__DI__))); 
  int __cxa_guard_acquire(__guard *g) { return !*(char *)(g); };
  void __cxa_guard_release (__guard *g) { *(char *)g = 1; };
  de:	81 e0       	ldi	r24, 0x01	; 1
  e0:	80 93 3c 01 	sts	0x013C, r24

foo & getFoo ()
{
  static foo x;
  return x;
}
  e4:	84 e4       	ldi	r24, 0x44	; 68
  e6:	91 e0       	ldi	r25, 0x01	; 1
  e8:	08 95       	ret

Thanks jwatte for clarifying something that was just lurking in the recesses of my mind. Now I know, static variables inside a function, and global static variables, are simply not identical in functionality.

bperrybap:
I have yet to see a compiler do anything special for initialized data variables as shown
in the earlier example inside the function.

See the above example, Bill.

bperrybap:
I have yet to see a compiler do anything special for initialized data variables as shown
in the earlier example inside the function.
The initialized data is handled in the startup code before main.

Further tests seem to indicate you are correct for simple variables, like int.

Nick,
I think you misunderstood. I was not referring to your example.
The previous example I was referring to was the one by jwatte.
The one that showed a simple loop() function and
claimed that using a static unsigned long was not ISR safe and that
the compiler was creating hidden code to do a run time check each time the function was called to determine
if the variable "counter" should be initialized.

That is simply not the case for that example.

--- bill

Even in the field of safety-critical software, there is argument over whether variables should always be declared a locally as possible. I'm of the opinion that they should be, for the following reasons:

  1. If you declare a variable in the smallest enclosing scope in which it is used, then the program is clearer to read: you know that the variable has no meaning outside that scope, can't be directly modified outside that scope, and should be initialized within that scope before it is used. This applies not only when the program is worked on by multiple developers, but also to you when you come back to the program a year after you wrote it.

  2. Similarly, the compiler or static analysis tool can warn if the variable is not "definitely initialized' (in Java parlance). [However, the Arduino IDE runs the compiler at a low warning level so that it doesn't give these warnings.]

  3. The compiler can often generate better code when variables are declared in the smallest enclosing scope, e.g. it can avoid storing the value of a nonstatic variable that is about to pass out of scope, or even keep the variable in a register all the time. So the code tends to be faster and smaller. There is an exception that has already been noted, which is that non-global initialized static variables of non-primitive types have their initialization deferred until they are first 'executed', which means the code has to maintain and check a flag.

  4. A global variable always occupies memory, but a local nonstatic variable only occupies memory when the function or block (depending on compiler) containing it is being executed.

bperrybap:
That is simply not the case for that example.

You are correct; for simple plain-old-data initialization, the compiler is smart enough to just make it part of your data segment.

If your initialization has side effects, then that's not generally the case:

unsigned long func() {
  static unsigned long first = millis();
  return milllis() - first;
}

The language standard is written loosely enough that you can't guarantee that the compiler will optimize simple data copies, though -- if you port to some other compiler, assuming it's smart enough may get you in trouble.