Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Global vs. local variables

Status
Not open for further replies.
When I was learning to code in C on microcontrollers, we used tons of global variables - quite the opposite of how we learned to code in higher level languages. I find myself in every project trying to weigh whether to use global or local variables depending on what I'm doing.

I'm just wondering, what factors do you consider in your project when making a variable global vs. local for microcontrollers?

I usually use 16bit MSP430 MCUs from TI.
 
I tend to use local variables wherever possible but if I have to pass lots of variables to a function then I consider using global variables. The main consideration is ram and stack usage, with simple code you have enough ram to make everything global. More complex code will require you to use more local variables to preserve ram.

In the case of the MSP430 which has 16k of ram I would go the local route simply because it's easier to manage and debug. The global route is more appropriate with chips such as the PIC16F88 with only 368 bytes of ram and an 8 word stack.

Mike.
 
Local variables take up a lot less memory, so if you can contain everything within a single function, that would be ideal. You only use global variables if they will be needed throughout the entire program, rather than just one function. That's probably the simplest way to put it.

Regards,
Matt
 
As a general rule, you should keep the scope of a variable as small as possible. Also declare the variables as late as possible.

Here is an example from a great C book "21st century C":

Bad style:
Code:
#include <stdio.h>

int main(){
    char *head;
    int i;
    double ratio, denom;
    denom=7;

    head = "There is a cycle to things divided by seven.";
    printf("%s\n", head);
    for (i=1; i<= 6; i++){
        ratio = i/denom;
        printf("%g\n", ratio);
    }
}

Good style
Code:
#include <stdio.h>

int main(){
    double denom = 7;
    char *head = "There is a cycle to things divided by seven.";

    printf("%s\n", head);
    for (int i=1; i<= 6; i++){
        double ratio = i/denom;
        printf("%g\n", ratio);
    }
}
 
Last edited:
There is two ways of looking at this.... Global variables are better for some applications, locals are better for others.

When using global variables ( 100% better for the stack ) your program will run faster and smoother, but it becomes messy when you have ALL your ram locations used up...
Locals are better to use if you don't use nested functions... If you get too deep, you WILL run out of ram.

Most game writers will use globals... No parameter passing, no stack issues.
Application writers will use more local varables.

All large data structures are better being global.... Then the use of pointers will keep the stack at bay....


Mr T.... Do you think it wise to post code snippets using uninitialised pointers? People do this on a large scale and fall foul of the results...
 
Last edited:
As a general rule, you should keep the scope of a variable as small as possible. Also declare the variables as late as possible.
...

That is a good rule for general C coding, but can be a poor rule for C coding for microcontrollers. Some compilers will allocate a global RAM address for every local variable, so there is NO memory saving using local variables.

A good memory saving could however be achieved by manually using re-usable global variables, which can be extremely effective for saving RAM on a microcontroller but is technically "bad C".

Also in your "good" example I question this;
for (int i=1; i<= 6; i++)

As it is typical to have many for loops throughout the program and i is a perfect example of a re-usable variable.

Working with small micros and limited resources I would suggest an almost opposite approach; to use a lot of global vars and decleare them at the top of the code, and re-use whenever possible. That more closely resembles an "assembler" approach which is more efficient for resources on smaller micros and also forces the person to code in a way that requires good knowlege of what the code is doing with the variables.

On a PC where RAM is unlimited and there are faster/slower types of storage it is better to use more of a "proper" C style where you keep variables very local and let the compiler handle all the rest for you.
 
Local variables are one of the elements of structured programming.

They are only a bad idea when the processor is limited via speed or ram. They are generally not favored by minimalists.

Locals enable us to limit scope and to a limited extent do cooperative sort data hiding. In the following untested code fooBarData is local rather then global and has range checking.

Code:
#define PUT 0
#define GET 1
#define FOOBAR_ERROR 1000

#define fooBarType int;
fooBarType fooBar(char getPut, fooBarType value)
{ 
  static fooBarType  fooBarData;  // static makes fooBarData persistent between calls to fooBar
  if (getPut == GET)
  {
   return fooBarData;
  }
  else if (getPut == PUT)
  {
    if ((value > 0) && (value <100))  // whatever data verification is useful
    {
       fooBarData = value;
       return value;
    }
    else
    {
      return FOOBAR_ERROR;  // one could use other error reporting methods
    }
  )  
}

This may look like a lot of work but it has a big advantage. No matter how complex the program gets or how many times fooBarData is modified, all debugging involving fooBarData are restricted to fooBar().
 
Last edited:
Some compilers will allocate a global RAM address for every local variable, so there is NO memory saving using local variables.

I've not come across this in any compiler I've used. Care to name and shame em?

Mike.
 
FooBar..... I always wondered why they use a military saying for this!!! ( originally it used to be FuBar!! )

I've not come across this in any compiler I've used. Care to name and shame em?

Oshonsoft until just recently.... other basics aswell ( I know we're talking about C in general )
 
Last edited:
We used to use Fubar all the time in the 80's to describe a complete crash where the screen was full of random colours. F#$%^ed up beyond all recognition was how it was explained to me.

Snafu also seems to be sneaking into the language more.

[/offtopic]

Mike.
 
We used to use Fubar all the time in the 80's to describe a complete crash where the screen was full of random colours. F#$%^ed up beyond all recognition was how it was explained to me.

Snafu also seems to be sneaking into the language more.

[/offtopic]

Mike.

Lets not go there.... I knew someone would post it!!!
 
Also in your "good" example I question this;
for (int i=1; i<= 6; i++)

As it is typical to have many for loops throughout the program and i is a perfect example of a re-usable variable.

Usually compilers are very good at optimizing loops like that. If you use global re-usable variable for "int i", you better be careful not to use the same "i" in interrupts etc.

Also if you use global variables in interrupt routines, you usually need to declare them as "volatile" and this prevents the compiler from optimizing the variable resulting to very inefficient code.

I agree that the world of microcontrollers is different from PC application programming. Some "good practices" don't apply and sometimes "Bad style" is better. But, if you are not sure what to do, use the best practices and guidelines. And every embedded C programmer should know their compiler.. what it does and how it optimizes code. Knowing your compiler is very important.
 
Last edited:
I've not come across this in any compiler I've used. Care to name and shame
...

MikroC does this. Any local vars declared inside functions are just allocated to a fixed RAM location in the PIC.

I imagine this is common with C compilers for microcontrollers? What would be the alternative? The compiler would have to allocate some area inside the PIC RAM for all the local vars to share (how much?) then ensure that there is no possibility of overlaps during runtime where two functions might both use the same RAM location for their local variable. Then somehow get the PIC to dynamically assign the var to any free location (with bank switching) when the PIC is running? That sounds like code bloat.

Alternatively it could try and work out which functions would be in use when others cannot be in use, and just overload a few local vars to the same location? That sounds like a reduction in RAM savings and is still a level of complexity and possibility things may go wrong. Understanding that in a PIC the hardware registers and PORT pins might be the thing that determine if a function can get called, how does the compiler know whether any function will get called at what points?

And if it trys to err on the side of caution with each variable (not knowing what functions may be called)... it gets closer and closer to that model of just assigning one global RAM location to each local var (which my compiler does).

Have you checked your compiler? Make a few functions and see if the compiler allocates a RAM location for each local variable, then maybe try calling those functions based on what a PORT pin does.

MisterT said:
re "for (int i=1; i<= 6; i++)"...
Usually compilers are very good at optimizing loops like that.

Really? I've never tried doing;
Code:
for(int i=0; i<1000; i++) bigbuffer[i] = 0;
for(int i=0; i<100; i++) littlebuffer[i] = 0;

But that just looks like poor programming practice to me compared to re-using a global i var.

MisterT said:
If you use global re-usable variable for "int i", you better be careful not to use the same "i" in interrupts etc.

Absolutely agreed! But I would add that with interrupts etc on microcontrollers the user should be well aware of issues with all global vars not just re-usable ones, even variables used to move data in/out of the interrupt can have issues, especially multibyte vars.
 
I've never tried doing;
Code:
for(int i=0; i<1000; i++) bigbuffer[i] = 0;
for(int i=0; i<100; i++) littlebuffer[i] = 0;

But that just looks like poor programming practice to me compared to re-using a global i var.

Only reason to use global "int i" in a situation like that would be to optimize the two loops like this:

Code:
int i=0;
for(i; i<100; i++){
    littlebuffer[i] = 0;
    bigbuffer[i] = 0;
}

for(i; i<1000; i++) bigbuffer[i] = 0;

I would still keep the scope of variable "i" as small as possible. Inside the function, not global.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top