"static" global variables, passing variables between functions

Hi, So far, I've been using global variables to pass values for integers between functions that need to use and modify them. I've read that the alternative to that is to pass by reference. Is there anything wrong with using global variables to pass values that are needed by multiple functions?

In regards to global variables, I don't understand the difference between a static global variable and non-static global variable. For example:

static int shared_value;
void setup() {
}


void loop() {
}

If I left the static out of declaring "shared_value", it doesn't seem to effect the program.

Thanks!

It makes coding easier when the functions you write don't have to name globals. Then you don't have to write a separate version for every different variable to operate on.

Then you don't have to write a separate version for every different variable to operate on.

Nor do you if you use globals as you can pass a global to a function. Whether this is sensible or desirable is another matter.

UKHeliBob: Nor do you if you use globals as you can pass a global to a function. Whether this is sensible or desirable is another matter.

Of course if you go by the whole context that I wrote, the part that starts with "Then" makes more sense. Add in the context of the question.... globals versus passed references and what was I writing about?

I like to make my globals static because then you can get the "defined but not used" warnings for them.

Static in the context of a global variable means that it is only accessible in the file it's declared in. Makes no difference therefore if you have a sketch that consists of a single source file.

Google should find you enough reading on the subject of global variables to last a lifetime. In short though, a reason to avoid them is that when you're trying to debug something relating to a global variable, your search area for the problem is the entire program. A few hours wasted on such an issue should be enough to illustrate why people avoid them.

General rules of Scope, Lifetime, and Initialization:

Scope (where the variable is visible): Global: Everywhere in every file in the program (except in a block with a local variable of the same name). static Global: Everywhere in the current file (except in a block with a local variable of the same name). Local: Only the block (enclosed in { and }) where the variable is declared (but not in enclosed blocks with a local variable of the same name). static Local: Only the block (enclosed in { and }) where the variable is declared (but not in enclosed blocks with a local variable of the same name).

Lifetime: Global: Forever. static Global: Forever. Local: Only exists while the block is executing. static Local: Forever.

Initialization: Global: Once at sketch start. Defaults to 0. static Global: Once at sketch start. Defaults to 0. Local: Each time the block starts. Defaults to UNINITIALIZED. static Local: Once at sketch start. Defaults to 0.

One thing that I have always been unclear about is whether it is safe to return a variable declared within a function. It appears to work but is that just luck ?

UKHeliBob: One thing that I have always been unclear about is whether it is safe to return a variable declared within a function. It appears to work but is that just luck ?

Yes, that is just luck. Local variables are created on the stack. Once the function in which they are declared exits, the data for those variables is still on the stack, but BELOW the current stack pointer. Any stack usage, even an interrupt, can over-write that data, changing its value. If you're going to return data from a function, it must NOT be local data. Regards, Ray L.

UKHeliBob:
One thing that I have always been unclear about is whether it is safe to return a variable declared within a function. It appears to work but is that just luck ?

What else would you return? If it was a global variable there would be no need to return it?

…R

Robin2: What else would you return? If it was a global variable there would be no need to return it?

...R

My thoughts entirely, but it conflicts with what Ray says in post #8

No wonder I am unclear.

Integers and floats are passed and returned "by value". What is returned is a copy of the contents of the variable. Because of that it is always safe to return local integers and floats.

Structures, Objects, and arrays are passed "by reference". What is returned is the address of the variable. That is a problem if you return the address of a (non-static) local variable. That variable goes "out of scope" and the memory it was using can be used for something else (like an interrupt service routine local variable). It can be clobbered at any time, even before you have a chance to make a copy of the contents!

So: Integer and float types: OK. Other types: NOT SAFE.

Robin2:
What else would you return? If it was a global variable there would be no need to return it?

…R

Those are NOT the only options. You can return a static variable that is out of scope for the calling function. There are several other options as well, such as a pointer to a newly created object, or array.

Regards,
Ray L.

johnwasser: So: Integer and float types: OK. Other types: NOT SAFE.

I respect your knowledge but you are confusing me. This statement may apply to returning pointers or references to objects perhaps, but...

MyObject doSomething(int a, int b)
{
  MyObject obj;
  obj.x = x;
  obj.y = y;
  return obj;
}

...the object's copy c'tor gets called to make a copy of the local object, and that is what the caller receives.

in this example, if obj is declared static, you can (as pointed out) safely return a reference.

in the context of the above, this is safe:

MyObject someObject = doSomething(val1, val2);

or else what would be the point of returning something from a function for anything besides a primitive?

BulldogLowell: I respect your knowledge but you are confusing me. This statement may apply to returning pointers or references to objects perhaps, but...

This is safe, because an int is always passed by value, so a COPY of x is returned to the caller.

int someFunction(void) { int x = 5; return x; }

This is NOT safe, because arrays, structs, objects, etc. are passed by REFERENCE. so a pointer to the original object is returned. That object exists on the stack, so can be over-written after the function exits.

char *someFunction(void) { char s = "Hello"; return s; }

This is NOT safe, because you are returning the address of x to the caller, and x exists on the stack, so can be over-written after the function exits.

int *someFunction(void) { int x = 5; return &x; }

This IS safe, because the Blivet object is created on the heap, and you are returning a pointer to that heap object, which persists after the function exits.

Blivet *someFunction(void) { Blivet b = new Blivet(); return Blivet; }

Regards, Ray L.

RayLivingston: Those are NOT the only options. You can return a static variable that is out of scope for the calling function. There are several other options as well, such as a pointer to a newly created object, or array.

I think that is outside the scope of the question :)

...R

Pass references to globals and update any that should be updated before exiting the function: SAFE.

If you have a group of globals that get worked on together, make a struct or class object of them and pass a single reference to that rather than multiple references (2 bytes each go onto the stack).

arusr: So far, I've been using global variables to pass values for integers between functions that need to use and modify them. I've read that the alternative to that is to pass by reference. Is there anything wrong with using global variables to pass values that are needed by multiple functions?

In microcontroller code? No. In big, lumpy, web-application software with multiple layers written by a team of people? Yes. Good practise is contextual.

References are ok, but they do involve passing pointers around and de-referenceing them. It's additional overhead. The main benefit is that you can pass different variables into the same function, if you need to.

The other way to accomplish this is to use return values.

In regards to global variables, I don't understand the difference between a static global variable and non-static global variable.

Global variables are static. They have static [u]storage class[/u] and global [u]visibility[/u]. Static variables defined in a block also have static storage class, but their visibility is limited to the block they are in.