variables global,local,static and constants

Most tutorials I see use a lot of global variables. And use variables where it would make sense for a constant
ie:
int pinSensorInput=5;
vs
#define pinSensorInput 5

elsewhere, I see the use of global variables when it's only used loop(); why doesn't anyone use static variables?

I ask because I am starting to think of the limited space -- do global variables operate with less memory than static? less (machine level) instruction steps?
What does one gain by using global variable instead of a constant?

I seem to recall this being discussed before, but the brief answer is to use a constant, eg.

const int pinSensorInput=5;

By putting "const" there the compiler can optimize, and probably it won't take any memory at all.

Thanks; I hadn't seen that in any examples -- any idea about using static variable w/in loop() vs. global variable?
I like to do things that seems to be against Arduino convensions (Use Hungarian notation, keep global vars to a minimum, use macros where appropriate,...)
I haven't reached the limits yet; but I suspect I will when my project is done; so I'll need to have ideas to optimize memory vs speed of code (Yes, I know they can conflict).

thank you.

Using a static variable in a function has no different implications to a global variable ( to the function with the static var ). Everything else however will either not see the variable, or have access to it, depending on weather its static or global respectively.

Thanks Pyro -- I know / understand that bit -- I am after does one have a benefit over the other in the area of memory usage.

Either variable is subject to optimization.

If the compiler can see that nothing writes to them it may evaporate into load data commands and use no ram at all.
The compiler can do the least with it if you take a reference/pointer that the compiler cannot follow; something like an array of pointers where the index used to access it may come from an external/interrupt source ( analogRead, switch,... ).

The compiler doesn't need "const" to optimize out things that are blatantly obvious either. Infact sometimes you have to use "volatile" to stop it from doing so.

EDIT: Globals have lots of things that can cause nasty headaches, if only one function/scope needs the persistent data then go for the local static.

What pYro_65 said shouldn't been trivialized. Defining a variable inside a function (e.g., function scope) means it cannot be accessed outside that function. The data encapsulation that the static data qualifier brings to the table is a huge benefit, especially with such limited debugging facilities available in the Arduino IDE. It's all the better when it doesn't impact code size.

econjack:
What pYro_65 said shouldn't been trivialized.

What exactly are you referring to?
Static locals have the same scope as auto locals, the benefit is persistence.
File scope/member static variables are limited to the scope they are defined in.
Also local statics have no implication on code size, how it is used determines the potential for optimization.

I suppose that what it amounts to is that resources on a small microcontroller are more fundamentally "global" than in a purer computing environment. You can make pinSensorElement as locally scoped as you want, but it will still be a globally accessible "thing" whose purpose probably doesn't change.

#define for constants is pretty out-of-style these days ("const" or "static const" replaces it.) I'm not sure I always agree, but...

In general, the compile does a good job of optimization.
Accessing a local variable is slightly cheaper than accessing a global variable (2-byte "LD R, (sp)offset" style instruction vs 4-byte "LDS R, memloc" style instruction), but incurs the overhead of setting up a stack frame, and you can start to worry about stack growth exceeding memory. So it's hard to generalize that one is "better" than another.

There is no particular advantage to using globals and #define in Arduino sketches; it's just that a good portion of the code you'll find on-line is written by people with little programming experience and their focus is on getting it working, not the niceties of software engineering.

Also, because Arduino sketches tend to be small, you can get away with techniques that would cause you problems on a big project.

If you prefer to use static and const though, you can do so without issue.

What does one gain by using global variable instead of a constant?

Well as a non software guru (I program best with solder) I like using global variables on my small to medium sketches as it places all the variables I'm going to use directly at or near the start of my sketch. It seems to help me in debugging phase to think and perhaps throw in serial print statements to help track down errors.

For a micro-controller and a single programmer (me) it just makes sense to break a lot of the variable recommended scoping 'best practices' rules. I understand the protection that good variable scoping allows but still find using mostly global variables works better for me. However I do use local automatic variables for example as the index counter in if statements. And of course the arduino library functions I use almost always have internal local variables that I don't have to be concerned with and would make no sense to have them use global variables.

Lefty

pYro_65, #7:

What I was trying to say was that using a static inside a function gives the persistence he needs plus the added benefit of encapsulation. True, it may not make much difference in relatively short program code that is typical here, but I worked on one program about 30 years ago with over 800,000 lines of code and it sure can make life a little easier when you use encapsulation wherever you can. Given the costless decision here, I see no reason not to use a static with function scope.

The main reason the examples you read have so many globals is because the authors don't know any better. Most Arduino "tutorials" aren't written by programmers, but by people who have picked things up as they have gone along and have never been properly taught programming (the same could be said for the whole of the Arduino environment...)

I was always taught that variables should be defined in as limited a scope as the language allows:

  • At the start of a function if it is used throughout a function
  • In a while() block if it is used only within that while() block
  • Iterators defined in a for() loop unless they need to be referenced afterwards (like with linked lists, for instance)
  • Never define a variable in a switch's case block, unless it is within a while(), for() etc inside that case.

Also I was taught to declare all my variables together at the start of their scope, not half way through a scope like Java programmers seem to like doing - makes it easy to see what variables are used within that scope.

majenko:
Also I was taught to declare all my variables together at the start of their scope, not half way through a scope like Java programmers seem to like doing - makes it easy to see what variables are used within that scope.

I found myself nodding at most of your post, but this last part I think is a holdover from ā€˜Cā€™ versions where local variables were only allowed to be declared at the start of a block. C++ is better IMO in allowing variables to be declared at any point - it makes it easy to only declare a variable at the point its initial value becomes known, thus preventing any possibility of referring to the uninitialised variable. In effect this gives you another way to limit the scope of the variable, which is always good.

PeterH:

majenko:
Also I was taught to declare all my variables together at the start of their scope, not half way through a scope like Java programmers seem to like doing - makes it easy to see what variables are used within that scope.

I found myself nodding at most of your post, but this last part I think is a holdover from 'C' versions where local variables were only allowed to be declared at the start of a block. C++ is better IMO in allowing variables to be declared at any point - it makes it easy to only declare a variable at the point its initial value becomes known, thus preventing any possibility of referring to the uninitialised variable. In effect this gives you another way to limit the scope of the variable, which is always good.

Wherever you define a variable in a scope it is defined (though not necessarily available) in the entire scope. Defining it at the start, while not necessary in more modern versions of C / C++, is more readable in that you can see "These are the variables used and what they are" without having to trawl through all the source code looking for the definition of a variable just to find its type - you know where it should be; at the top. Plus, you should always get into the habit of initializing a variable to a default, even if it's just NULL. With decent compiler flags set you soon know if you have a variable that's used before being assigned...

majenko:
you can see "These are the variables used and what they are" without having to trawl through all the source code looking for the definition of a variable just to find its type

That's what Hungarian notation is for... let's you know instantly the variable's scope & type.

I'm going with the "examples are not written by programmers" theory...

majenko:
Also I was taught to declare all my variables together at the start of their scope, not half way through a scope like Java programmers seem to like doing - makes it easy to see what variables are used within that scope.

Actually, with class variables, declaring them just before using make a lot more sense. For example:

...
SdFile myFile;
myFile.open(filename, O_READ);
...

Let's say this code needs to make various decisions about whether or not the file needs to be opened. To have the variable declared half-way through the function means that the time (and memory) needed to create an instance of SdFile is not expended if it is never needed.

Also it ties the "open" to the variable name, and thus you can see what is being opened (on the previous line) rather than having to scroll back and see what "myFile" is exactly.

Well, the whole "loop()" structure of an Arduino sketch isn't terribly well match to the use of local variables.
Yes, you could use "static", but that would be an "added complication" for the beginning user.
For all the (mis)use of global variables in Arduino sketches, it relatively uncommon for them to be abused, either.
(Some of which is because functions in general don't get used as much as they should.)

There are of course some things in the Arduino world that use global variables because there is no infrastructure to allow the usual alternatives (messages, events, etc.)

Hungarian notation is one of the biggest stupid ideas ever invented.

Didn't Microsoft use it fairly extensively?

Anyway I agree, I don't use it at all these days. It's like saying, instead of:

give bone to Fido
give bone to dogMaleBlackShortFido

Who cares?