Basic Programming question - use of variables within functions

Hi all,
I've got a question due to using global variables within sub routines:

This is a code example with a global variable, which is used and changed by a subroutine. The program works aktually. As far as I read this is not the way it should be handled. I suggest it should be done with pointers. Basically I unterstand the principle of pointers.

My problem is why should I use "complicated" pointers when the code is still working. When will I get into trouble with my code?

</>

int supervar = 9;

void loop()
{
 changeme();
println(supervar);
delay(100);
}

void changeme()
{
 supervar = supervar++;
}

</>

Thank you very much!

BR
Chris

global variables are fine for small programs. but you don't want every variable to be global, having local variables within functions will make the code easier to read and maintain (i.e. debug).

passing pointers to a function will also make the function more reusable

That depends on what you want to do

You could pass a variable to the function, have the function change the variable and return it to where it was called then use the new value of the variable

Hi UKHeliBob,
thank you for your reply. I do not understand why it is a problem changing a global variable within a sub function.
I know, I could commit the value of the variable and return one single variable with the sub function. But why should i go the long way if I could only directly access the global variable within the sub function.

BR
Chris

Almost any program could be made working with global variables.

Pointers are a - step in between -

If you imagine a code 5000 lines long using in summary 100 or more variables the chance that you loose oversight is higher than in a small code.

If you change a global variable in 25 functions it will be hard to track down where a certain change come from.

The not so complex / difficult thing would be to use parameters and return-values

int myFunct (int myParameter) {

  int myLocalVar = myParameter;

  myLoaclVar += 123;

  return myLoaclVar;
}

int myGlobalVar;
int myOtherGlobVar;

myOtherGlobVar = 17;

// handover value of variable myOtherGlobVar to the function
// store result in variable named myGlobalVar
myGlobalVar = myFunct(myOtherGlobVar); 

coding it this way makes it easier to follow because the line where the function gets called the value of a vraiable is handed over as parameter and the function has a return-value that gets stored in a variable

this way is much harder to follow

void myFunct () {
  myLoaclVar = myOtherGlobVar + 123;
}


int myGlobalVar;
int myOtherGlobVar;

myOtherGlobVar = 17;

// myFunc gets called but there are no hints what does myFunc do???
myFunct(); 

best regards Stefan

It is not a problem per se, but the use of global variables in large systems, particularly ones with multiple program modules, perhaps programmed by several people, is regarded as bad practice because it is easy to become confused as to the value of such variables when it may be changed anywhere in the program

In small programs with only one programmer the same problem is less likely to occur so global variables are more acceptable but still need to be used with care

The most common problem that I have seen here when using global variables is when there is also a local variable with the same name. You need to be very sure which of them is being accessed, used or changed so such a combination is definitely best avoided

It is nice to get some code off the main sketch anyway with any more complex system and doing it in a way that is encapsulated and protected makes weird results less likely. I.è make or use a library.

You can have great button functionality in a library which is then easy to use and read in the main sketch and variable x can be used in both without conflict

Things to remember if you make everything global:

  • then it all exists for the life of the program, and you will run out of available memory much sooner
  • and a variable is doing something unexpected, then when debugging, you have to consider every location in the code that modifies that variable.
  • there is a constant temptation to modify that variable in functions that really shouldn't, just because... Good code design compartmentalizes your code so that this isn't a temptation.
    If your answer is still, "but I don't understand", then consider that it's possible you just don't have enough experience yet to understand. A moment will come, likely when you've been banging your head against a bug, when you suddenly realize why.
    C

Further to that, the other side:

  • if you keep variables local to your subroutines, then the memory they chew up is automatically freed when the function returns, keeping memory use lower
  • if functions A and B are the only functions modifying a parameter, you have limited scope for debugging, you know where to look.
    C

You can make all your variables global, including the variables you use in your for loops. You can put all your main code in loop rather than write functions. You can avoid creating any classes.

But, using some or all of those things makes your code easier to debug and so after you've spent a happy couple of hours trying to figure out why one of your for loops isn't working as you expected, you may be more amenable to the idea of local variables, information hiding and encapsulation :wink:

As a general rule of thumb:

  1. You want the access and lifetime of any given variable to exist in the smallest possible scope it can.
  2. For function parameters you need to decide if it's more applicable to pass by value (i.e make a copy) or pass by reference/pointer.

As pointed out above, following these rules will help you with everything from total program memory size, runtime memory size, debugging, readability, reuse and more.

why have a sub-function?

And what is a sub-function anyway ?

Instead of global variables, you might want to consider using static variables. They act like global variables, but are local to a function (sort of).

Additionally, instead of passing a pointer to a function, in C++ an argument can be passed by reference. This also allows a function to modify a variable.

Below are examples of these concepts for your example code.

void loop() {
  static int supervar = 9;
  changeme(supervar);
  println(supervar);
  delay(100);
}

void changeme(int& supervar) {
  supervar++;
}

Note that the best choice always depends on the situation.

However you decide to write your code, there will be someone who will say "No, that's not the way to do it."

1 Like

reusable is a big word. It makes it possible to have libraries, for example. Meaning among other things that you can save time on coding and testing by just copying reusable code to another program. You know it works. And you don't care how. Details can be hidden. You only need to know what it does, and how to exchAnge data with the function.

The point being that your function changeme() here

is tightly coupled to the rest of the program and this means that for it to work, any program that uses it must also have a global variable with that name.

As it has been said multiple times in multiple ways in this post, changing a global variable from within a function does work, but is not a good programming practice.

Take a look at structured programming, and specifically, to common coupling

Elephant in the room...

2 Likes

Hi all,
first thank you all verry much for all your comments!

It's not easy to understand - I think my programms are to small to really realize the benefit of classes librarys and so on. But you defenetly opend my mind.
The main point as I understood, principally global variables are not a problem as they are - but it can be very complex at larger programs and produce bugs due to trapping the programmer.

I try to get more into the class and library stuff. My problem in mind is how to divide the individual parts of programms into enclosed sections... I will think about it :wink:

Thanks for your help!
BR
Chris

1 Like

You are already doing it by creating functions out of the loop which you call in the loop. Next thing you will need to do is create groups of functions to do something a little more complex which you can organise in a class. Then you will get annoyed at them all taking up space at the bottom of your code and push them into another tab and make a header file and a .cpp file. Look up object oriented programming

me personal I use ready to use libraries which most of them have classes inside.

For your own code it is not nescessary to put everything into classes and libraries.

You can stay on the level of functions that are defined in your *.ino-file with almost the same comfort and security.

On the level of functions it is very easy to decide what should be inside a function: a part of the code that does one single thing.
lines of code that are a senseful unit.

examples:

  • requeste a value from a sensor
  • send the characters for titles and values to an LCD
  • save configuration values to EEPROM or flash or SD-card
  • append one line of data to a file on SD-Card
  • use some values to calculate a result with these values

If you post your most complexe code you have written so far I can make suggestions on how to divide this code into functions.

best regards Stefan