Scope of setup, loop and body variables

Hello,
I am trying to avoid using global variables as I've read on C++ sites that it is generally frowned upon. In order for me to do so, I need to better understand how Arduino handles scope of variables in three areas: the body, the setup function and the loop function.
Please look at the code below:

int bodyvar=2;

void setup() {
  int setupvar=4;

}

void loop() {

int loopvar;

loopvar=bodyvar+setupvar;

}

First note that this program does NOT compile as it gives the following error

error: 'setupvar' was not declared in this scope

My questions are as follows:

  1. if arduino calls setup() at the start of a program, why aren't variables defined there available to loop()?
  2. If I don't want ANY global variables, would I declare and initialize them all in loop() as follows?
void setup() {

}

void loop() {
int bodyvar=2;
int loopvar;
int setupvar=4;

loopvar=bodyvar+setupvar;

}

Is there a downside to this approach (for example, are all of the variables redefined each time the loop comes around)?

Thanks

  1. if arduino calls setup() at the start of a program, why aren't variables defined there available to loop()?

Because the "scope" of a variable; which is where is can be reference from; is defined by where the variable is declared. When you declare a variable inside of a function like setup(), that variable NAME is only available inside THAT function. The variable itself will (or can) exist in storage that disappears when setup() exits.
Part of the advantage to local variables is that there are NOT accessible to other functions; this means you can use a popular variable name like "temp" or "i" without worrying that you'll overwrite some other value of temp or i.

  1. If I don't want ANY global variables, would I declare and initialize them all in loop() as follows?

Yes.

Is there a downside to this approach (for example, are all of the variables redefined each time the loop comes around)?

Yes. Sort of. They are recreated each time the function runs, and are destroyed when the function exits (unless you also declare them "static.") So there is no danger of running out of space after you "redefine" them thousands of times. There is some overhead associated with creating the local variables, but there is also potentially LESS overhead in accessing them inside the function. A global variable MUST occupy a memory location, for example, while the compiler can optimize a local variable so that it never leaves a register.

I've read on C++ sites that it is generally frowned upon.

Well, yes. But most C++ sites are unlikely to take into account the details of getting a program working on a small microcontroller with only 2K of memory. Or that have the loop-type structure that arduino sketches use. You should use local variables for things that are really local, but the nature of embedded programming says that you are more likely to have variables that ARE and should be genuinely global as well.

2 Likes

memotick:
I need to better understand how Arduino handles scope of variables in three areas: the body, the setup function and the loop function.

Regardless of the functions, the scope and lifetime of variables is exactly the same as in C++. So the question about "how Arduino handles" is irrelevant. You need to find out how C++ handles it.

You need to find out how C++ handles it.

And you need to understand that loop() and setup() are nothing more than normal C++ functions.
They don't have ANY special behavior in Arduino, other than the way that they're called from the startup code.
(This is exactly the same as "main()" not being special on a desktop system...)

Wondering about the use of the word "body" here. Is it normal to call the parts outside the functions of a C program the "body"? (ie, the part above main() or above setup() in Arduino-speak?

If not, what is that stuff called?

what is that stuff called?

I call it "top level", and I think I've heard it called "global scope."

Above, or below, setup. It's global scope. Inside a function it is local scope.

int bodyvar=2;  // this variable is global as it is declared outside of any functions

void setup() {
  int setupvar=4;  // this variable is local to setup() as that is where it is declared
}

void loop() {
int loopvar;  // this variable is local to loop() as that is where it is declared

loopvar=bodyvar+setupvar;  // this fails because setupvar doesn't exist here, it only exists in setup()
}

I added some comments to your code
HTH

Wow, great responses everyone! I think this was the best replied thread I've ever had in terms of teaching me concepts. I'll try to mimic the approach to asking a question in the future.

Thanks again!

I had the same confusion with variable scope inside the 'loop' routine early on with Arduino

Your answer is here:
Arduino Variable Scope - Static Reference

Since the programming language is C++ and unlike a standard C++ program where the main function void main () {}.... you will quickly realize that the Aurduino void loop() {} is just simply a function that will be compiled into the program that goes to the board.

Also as it's name implies it will continuously loop.

So as the reference will imply, when you declare variables inside of the 'loop' function, you can use the syntax:

void loop {
    // Using static ensures the function will only create the variable the first time the function is run.
    static int a;        // Declares a variable but does not set it
    static int b = 10l  // Declares and sets a variable
    int c = 5;   // This variable is destroyed, recreated and reset to 5 each loop.

Hope that helps, it took me a while to find the answer so I thought I would clean up this post.

and unlike a standard C++ program where the main function void main () {}

The standard main() function takes arguments and returns an int.