global variables vs passing arguments to functions...

Greetings;

I read somewhere, that global variables should be avoided in programming. Not sure why, but being a rookie, I just accepted this.

Now I'm finding myself more and more often passing multiple variables to functions (most often void functions()).

Are there any advantages for one method vs the other?

I'm working with a mega 2560, just in case hardware plays a role.

Cheers

The primary advantage of passing a parameter is that, unless it is passed by reference, no values in the main program can be accidentally modified by any use of the parameter variable in the function. As a consequence, that also means that two or more different functions can not accidentally modify a value that is used by another function.

The other aspect is tidiness and conciseness. Consider how a common function like say, pinMode() would work without it. You would have to maintain two variables, assign values to them before every call:

pinNumber = 3;
pinModeType = OUTPUT;
pinMode();

Would you like to be stuck with that? :slight_smile: Imagine all the thousands of globals that would have to exist, and the effort of trying to avoid naming collisions...

Thanks Aarg,

That makes perfect sense. So I take it my passing variables is the right habit to develop.

Out of curiosity, which method is more memory efficient, both RAM and ROM?

I've been using the same name of variable inside the function as the one I'm passing. Is this safe, or will to bite me in the rear in the future...

Cheers

Parameter passing is usually more memory efficient because the memory allocated to the parameters is automatically de-allocated when the function returns to the main program. It is then available for the next function call to use.

trilife:
So I take it my passing variables is the right habit to develop.

Out of curiosity, which method is more memory efficient, both RAM and ROM?

I've been using the same name of variable inside the function as the one I'm passing. Is this safe, or will to bite me in the rear in the future...

It depends. Generally, it's best to minimize the number of globals you use wherever possible; when you have a bug that involves one of them, your search space to find the problem is the entire program. Better if it's a smaller area.

However, Arduino programs are usually not huge and the people writing them aren't software engineers, neither are they interested in becoming one. So globals can get the job done, even if it isn't the best way.

For memory efficiency, globals are likely consuming less memory. Unless you're writing recursive stuff though, the difference probably doesn't overcome the advantages of parameters.

Don't use the same name in your function parameters as the variables you pass. It's legal and won't do any harm until you make a typo and create a subtle bug where you pass one thing but use another. It's just another one of those things that can cause you hours of unnecessary debugging.

A function is supposed to be self contained, do a well defined job and be reusable for multiple inputs. If it touches a global, it might manage 1 and 2, but 3 is questionable.

The point is that the software engineering discipline is stuffed full of practices that help you avoid shooting yourself in the foot. Most of them were discovered when someone did exactly that. You don't have to use any of those practices, but the bigger your program gets, the more likely it is that you'll be glad you did. Passing parameters is just one of those practices.

wildbill:
The point is that the software engineering discipline is stuffed full of practices that help you avoid shooting yourself in the foot. Most of them were discovered when someone did exactly that. You don't have to use any of those practices, but the bigger your program gets, the more likely it is that you'll be glad you did. Passing parameters is just one of those practices.

Thanks Bill, is there a good text, which can point me in the right direction? I hate bullets in my feet, especially avoidable ones.

Cheers.

Code Complete is one I like. I'm sure there's many others.

As a non-software engineer, I can offer another point of view.
I have written what I consider some big programs, compared to most we are asked for help with in the forum, 25 pages when printed out, with all global variables, in a '328P, and not had space issues.

In fact the only time I ever had an issue was when I forgot there was only 1K of EEPROM and I was trying to use 2K and couldn't figure out why my data seemed to be getting corrupted.

Make everything global, and be careful with your code that some part doesn't access something you're not supposed to. I find that easy enough to do.

The question was not, "do local variables use more or less memory?", it was "do parameters use more or less?". I think everyone who replied above would agree that to forego parameter passing in favour of accessing global variables from a function, is generally not a good practice for many reasons. In some cases accessing a global directly might be faster, since a copy does not have to be made on the stack.

CrossRoads:
As a non-software engineer, I can offer another point of view.
I have written what I consider some big programs, compared to most we are asked for help with in the forum, 25 pages when printed out, with all global variables, in a '328P, and not had space issues.

In fact the only time I ever had an issue was when I forgot there was only 1K of EEPROM and I was trying to use 2K and couldn't figure out why my data seemed to be getting corrupted.

Make everything global, and be careful with your code that some part doesn't access something you're not supposed to. I find that easy enough to do.

Thanks CrossRoads. I'm way past 25 pages of programming for this project already. And from my days as an COP800 assembler programmer (mid-80s, anyone remember National Semi Conductor?) any time I use a snippet of code more than once, it becomes a sub-routine... I'm not abandoning global variables. They come handy as flags and I have some large struct arrays, which get transferred from EEPROM during setup.

I am also not a professional programmer. I take the view that within the project there are variables that need to be accessed by any part of the project, so I make these global. There are variables that are only used within a function so I make these local to the function, and static if I need them to keep their value between each call of the function. Then there are functions that are only used in one place and only ever update specific variables, so these functions would not have variables passed to them or returned from them, they just do what they do and update the relevant variables. Other functions are more general and get used in different parts of the overall program, so they will have variables passed to them are will return something.

The above is not fixed; a function that I initially envisage only being used in one specific place so not have any variables passed or returned might later find uses I had not originally thought of, so I will modify it accordingly.

Btw, the first 6 (?) arguments of a function live in the registers and not on the stack.

trilife,
When you compile, what are you seeing for dynamic variables and fixed storage?

CrossRoads:
trilife,
When you compile, what are you seeing for dynamic variables and fixed storage?

Hi CrossRoads;

Where do I look for that?

In the message window at the bottom of the IDE screen.

CrossRoads:
Make everything global, and be careful with your code that some part doesn't access something you're not supposed to. I find that easy enough to do.

For sure, you can make that work, but for me, that be careful bit is extra effort that I could get the compiler to help me with.

There's plenty of stuff in the toolbox, use the stuff that suits you. Except that weird squiggly thing that only PhD mathematicians can understand - nobody really uses that.

An analogy: Consider a master carpenter making a set of eight dining room chairs out of moderately expensive materials. He (or she, but he here) is going to the toolbox to get all the things that minimize error and time. For your three legged stool, you don't need to. He will use power saws, jigs, a drill press, 150 clamps, power sanders, a steaming box and a precision $15000 dollar cabinet saw. You're happy with a tenon saw.

But there is stuff he does, that once you've seen it, might flow down to your projects. "I've always wondered why on earth they do that" kind of thing. Or be happy with your tenon saw, just be sure it's sharp :wink:

wildbill:
There's plenty of stuff in the toolbox, use the stuff that suits you. Except that weird squiggly thing that only PhD mathematicians can understand - nobody really uses that.

Do you mean "~"? It's just a bitwise operator that inverts all bits (0->1, 1->0) in an integer. It's very useful (for example) to turn off a single bit: "x &= ~(1<<2)" will turn off bit 2 in "x".

christop:
Do you mean "~"? It's just a bitwise operator that inverts all bits (0->1, 1->0) in an integer. It's very useful (for example) to turn off a single bit: "x &= ~(1<<2)" will turn off bit 2 in "x".

If it seems too esoteric, you can use keyword 'compl', short for "complement" in its place.

aarg:
In the message window at the bottom of the IDE screen.

Sketch uses 28390 bytes (11%) of program storage space. Maximum is 253952 bytes.
Global variables use 1833 bytes (22%) of dynamic memory, leaving 6359 bytes for local variables. Maximum is 8192 bytes.

christop:
Do you mean "~"? It's just a bitwise operator that inverts all bits (0->1, 1->0) in an integer. It's very useful (for example) to turn off a single bit: "x &= ~(1<<2)" will turn off bit 2 in "x".

TOO COMPLICATED!
Why would you use that instead of:
x &= 0xfb;?