Are local variables generally preferred over global?

In summary, the conversation reflects a standard among computer programmers that local variables are preferred over global in terms of how the quality of a program is judged. This is due to various reasons, such as easier modification of code and better implementation hiding. However, there are also situations where global variables may be necessary, such as for synchronization purposes or in interrupt-driven routines. Ultimately, the use of global variables should be limited and encapsulated in objects with methods for manipulation.
  • #1
jack476
328
125
When I was taking my introduction to C class, our professor heavily stressed that we were supposed to use local variables except when indicated otherwise. When we used C for microcontrollers with the same professor, he had the same requirement.

Does this reflect a standard among computer programmers, that local variables are preferred over global in terms of how the quality of a program is judged?
 
Technology news on Phys.org
  • #2
jack476 said:
When I was taking my introduction to C class, our professor heavily stressed that we were supposed to use local variables except when indicated otherwise. When we used C for microcontrollers with the same professor, he had the same requirement.

Does this reflect a standard among computer programmers, that local variables are preferred over global in terms of how the quality of a program is judged?
Although there are good reasons to use global variables sparingly, there are many good reasons to prefer local variables over globals. For one, it's much easier to modify code, when needed, if the code doesn't modify global variables. For another, local variables hide the implementation of a routine better than when globals are used. Also, modular programming, with information passed in via parameters, decreases complexity, making it a better fit for large programming projects with multiple programmers.
 
  • Like
Likes Jaeusm
  • #3
Generally, you want to encapsulate your data accordingly. Why would you create a global variable if it can be defined in another scope. It also helps with readability. For example consider a loop. Would it be easier to comprehend the loop if the counter variable is defined globally? No! You would want to define it in the scope, which is in the for() line. To answer your question it is essentially standard to create variables relative to their scope, so don't create globals when you don't need to! It may not be easy to see this in a small program but when things start hitting 1,000+ lines it can become a nightmare tracking down variable declarations-especially if they are global.

As with most things, it depends on your application and design goals.
Statically declared global variables are not stored on the stack or heap. Instead they go in the .data section.
Maybe you have a limited stack size for security reasons and you want to save as much stack space as possible. One solution would be to statically allocate the data in .data instead of pushing all of it onto the stack.

Or maybe you have a small chat program with a vector container of users. You might have some functions that need the vector of users.
Code:
bool SendMessage(vector<string> USERS, string Message)
bool SendPoke(vector<string> USERS)
bool BanUser(vector<string> USERS)

Depending on your design, you may want to make vector<string> USERS global to use them everywhere.
 
Last edited:
  • #4
One usage for global or static variables is for synchronization purposes, such as mutexes, semaphores, ... . Another usage is for interrupt driven routines, often part of a device driver in a typical operating system, or for an interrupt handler in a small embedded system, since parameters can't be passed to an interrupt driven function in the conventional sense. Sometimes an interrupt driven procedure goes through multiple interrupts, and one way to deal with this is by setting one or more pointers to function in advance of the next interrupt for which logical step should be performed through a series of interrupts. Yet another usage is shared memory between processes, where effectively all of the shared memory is "global".
 
Last edited:
  • Like
Likes Silicon Waffle and Thomas Thelen
  • #5
In my world, a global variable is an accident waiting to happen. Why? Since it is global, it will be visible to all and everybody - and that means that they will try to extract information from it and possibly change it. I subscribe to the "information hiding" principle - if somebody want some specific information from your code, write a snippet that returns the information. It is the same thing with objects - always make all variables private. If somebody wants to access those variables, create a method to return the information you want them to have.
 
  • Like
Likes Samy_A and Borg
  • #6
Thomas Thelen said:
Or maybe you have a small chat program with a vector container of users. You might have some functions that need the vector of users.
Depending on your design, you may want to make vector<string> USERS global to use them everywhere.
No. You would encapsulate it in an object and create methods to manipulate it.
 
  • #7
Svein said:
No. You would encapsulate it in an object and create methods to manipulate it.
Which is why I said "Depending on your design". Not all designs are perfect.
 
  • #8
jack476 said:
When I was taking my introduction to C class, our professor heavily stressed that we were supposed to use local variables except when indicated otherwise. When we used C for microcontrollers with the same professor, he had the same requirement.

Does this reflect a standard among computer programmers, that local variables are preferred over global in terms of how the quality of a program is judged?

Yes. I've been working as a professional software developer for 20+ years and global variables are used sparingly and the more global variables a program has, the lower the perceived quality and ease of maintenance (also, your peers will make fun of you or deny you the rights to check in your code). The most common reason I come across global variables is to work around poorly designed function interfaces in multithreaded programs.
 
  • Like
Likes Silicon Waffle
  • #9
Thomas Thelen said:
Or maybe you have a small chat program with a vector container of users. You might have some functions that need the vector of users. Depending on your design, you may want to make vector<string> USERS global to use them everywhere.

Svein said:
No. You would encapsulate it in an object and create methods to manipulate it.
Then that object may effectively be a global or a static. Encapsulation in that case just hides individual members, not the fact that a shared instance of an object may have scope outside of any single function, thread, and/or process.
 
  • Like
Likes Silicon Waffle
  • #10
Okay, thanks for the advice.

The context for this is that I'm in an intro simulation and numerical methods class and we having to make a MATLAB script for a project tjat will find roots of polynomials up to order 5 using six different methods. My approach is that I want the program to prompt the user to input the coefficients, confirm that the polynomial has only real roots (we haven't covered techniques to find complex roots yet) by evaluating the discriminant, and then call each root-finding algorithm as a separate function. For some reason, I can only get that to work if I set the coefficients and bounds for estimation as global variables.
 
  • #11
Svein said:
If somebody wants to access those variables, create a method to return the information you want them to have.
Svein said:
No. You would encapsulate it in an object and create methods to manipulate it.
Best to strive even further, to make as many variables truly encapsulated as possible. If someone wants access, tell them to go away.
rcgldr said:
Then that object may effectively be a global or a static. Encapsulation in that case just hides individual members, not the fact that a shared instance of an object may have scope outside of any single function, thread, and/or process.
Agreed. At least in OOP, even getters and setters are to be avoided as much as possible IMO. You want to reduce the number of ways in which external factors can change the internal state of a module, and avoid external dependency on the modules internal state. Try not to make public member functions modify internal state.
 
  • #12
jack476 said:
Okay, thanks for the advice.

The context for this is that I'm in an intro simulation and numerical methods class and we having to make a MATLAB script for a project tjat will find roots of polynomials up to order 5 using six different methods. My approach is that I want the program to prompt the user to input the coefficients, confirm that the polynomial has only real roots (we haven't covered techniques to find complex roots yet) by evaluating the discriminant, and then call each root-finding algorithm as a separate function. For some reason, I can only get that to work if I set the coefficients and bounds for estimation as global variables.
IMO, it's reasonable to have the bounds for estimation as globals, but the coefficients should be a parameter (as a one-dimension array) of each the functions.

Stylewise, the names of the bounds should be all caps, so that they really stand out.

My $.02
 
  • #13
jack476 said:
When we used C for microcontrollers with the same professor, he had the same requirement.
Besides all the good points here on style and encapsulation, there's another hardware-specific reason, mostly for embedded devices, to prefer local variables (stack allocated) to global or statically-allocated variables, which is speed.

Most microprocessors have different types of internal RAM, with the lowest memory addresses typically being mapped to the fastest RAM. This is also typically the range which can be accessed using the least complex addressing mode (fewer and/or less complex CPU instructions). Since the stack is used for, for instance, return addresses when you call a function, it makes sense that the stack should reside in this fast access/fast addressing region.

I've seen people, in code for embedded devices, allocate variables, which are used only in the local scope, statically as an attempt at optimization since the processor then doesn't have to "allocate the memory over and over again". This is completely backwards. The stack is fast, and global/statically-allocated variables might even get allocated to external (slow) RAM, depending on your system configuration. Allocating more space on the stack typically has zero overhead, since it just moves a stack pointer a bit further.

In short: the stack is a wonderful place, but be careful with how much you fit on there (watch out for recursion!).
 
  • #14
milesyoung said:
I've seen people, in code for embedded devices, allocate variables
Were you in that code or were there people in that code? :oldeek:
 
  • #15
Mark44 said:
Were you in that code or were there people in that code? :oldeek:
It made sense when I wrote it!
 
  • #16
Ease of access of global variables is both an advantage and a disadvantage. Be judicious and know why you are choosing global versus local. Protecting a variable is good. Making it harder and slower to get a variable value is bad. When you hide information, be sure you know who you are hiding it from, and why.

Many real-time programs that I have seen have eventually run into execution time issues. It is discouraging when many programmer-years of effort has created elegant code that will not run fast enough. Function calls to access and/or set information are very slow.

That being said. 99% of the variables in a program should not be accessible outside of the local scope. Make them local.
 
Last edited:
  • #17
Jarvis323 said:
Agreed. At least in OOP, even getters and setters are to be avoided as much as possible IMO. You want to reduce the number of ways in which external factors can change the internal state of a module, and avoid external dependency on the modules internal state. Try not to make public member functions modify internal state.
Agree. But there is no rule that says that you have to accept the value in the "set" call. Creating a "set" method allows you to decide whether or not to change anything. A good idea is to return the "new" value, so the guy trying to change the variable can check if the "set" was successful.
 
  • #18
FactChecker said:
Many real-time programs that I have seen have eventually run into execution time issues. It is discouraging when many programmer-years of effort has created elegant code that will not run fast enough. Function calls to access and/or set information are very slow.
I heard that argument used when discussing system architecture with a professor in IT. His reply was: "Of course, if there is no requirement that the code should be correct, I can make it run extremely fast!"
 
  • #19
Svein said:
I heard that argument used when discussing system architecture with a professor in IT. His reply was: "Of course, if there is no requirement that the code should be correct, I can make it run extremely fast!"
However, if it doesn't run fast enough, it doesn't matter if it is correct or not. It will have to be rewritten. Good programmers can avoid misusing global variables. They can not speed up the hardware.
 
  • #20
FactChecker said:
Good programmers can avoid misusing global variables.
Yes, of course.
FactChecker said:
They can not speed up the hardware.
Easy. Wait a year. The hardware will be 20% faster...
 
  • Like
Likes Rx7man
  • #21
Are you referring to a global option that never changes? I would use a global for a constant, a singleton for a variable.

If I never want the value to change, it's just configuration
Code:
//config.h
namespace Config {
     constexpr static const float simulationGravity = 9.8f;
}//main.cpp
#include "config.h"
#include <iostream>
int main(int argc, char ** argv){
     std::cout << Config::simulationGravity << std::endl;
     return 0;
}

If I want the value to be changeable by the program itself
Code:
//config.h
namespace Config {
    static float & simulationGravity();
}//config.cpp
#include "config.h"
float & Config::simulationGravity(){
     static float singleton = 9.8f;
     return singleton;
}//main.cpp
#include "config.h"
#include <iostream>
int main(int argc, char ** argv){
     std::cout << Config::simulationGravity() << std::endl;
     Config::simulationGravity() = 4.5f;
     std::cout << Config::simulationGravity() << std::endl;
     return 0;
}
 
  • #22
FactChecker said:
Ease of access of global variables is both an advantage and a disadvantage. Be judicious and know why you are choosing global versus local. Protecting a variable is good. Making it harder and slower to get a variable value is bad. When you hide information, be sure you know who you are hiding it from, and why.

Many real-time programs that I have seen have eventually run into execution time issues. It is discouraging when many programmer-years of effort has created elegant code that will not run fast enough. Function calls to access and/or set information are very slow.

That being said. 99% of the variables in a program should not be accessible outside of the local scope. Make them local.

It's usually the algorithms and data structures that impact performance the most.

The issue that I think is really at hand when it comes to variable access, is that it's often harder, or slower, especially for beginners, in the short term to write good modular code. It's very quick at the moment to just throw a global variable at the top of the page.

The same thing goes when it comes to trying to generalize and reduce redundancy. It's often more time consuming to write good code, but the more critical and or large the project, the more important it is, and the more it will save you in time and quality in the long term.
 
Last edited:
  • #23
Jarvis323 said:
Performance issues are very infrequently the result of such trivial things. I'm not sure that there are many cases where using a global variable will help performance anyway. Usually it would probably hurt if it were not a constant because memory on the stack is quicker to access. It's the algorithms, and specifically use of data structures that makes performance issues.
I'm afraid I have to disagree here. A function call to get or set a variable value requires many more clock cycles. And programmers who are not aware of the issues run the risk of having function calls within calls within calls. I have seen large structures copied one member at a time from one structure to another using get and put functions. They can easily take orders of magnitudes longer than accessing the same data in global static memory. And, depending on how much data is being copied around, the programs can be unusable. Correcting the problem can require a complete rewrite of the code.
 
Last edited:
  • #24
These functions would usually be inlined by the compiler anyways.
 
  • #25
Jarvis323 said:
These functions would usually be inlined by the compiler anyways.
A lot of safety-critical applications allow only minimal compiler optimizations. And if you have to follow the MISRA-C rules, using inline functions is either not allowed or requires justification. You have to be careful about that.
 
Last edited:
  • #26
If you can't use optimization, then it would also be important to not use many high level data structures in general, for example the STL. For example, you will see about 10 times worse performance iterating over a C++ vector without optimization. If you have no-optimization requirements, for a critical performance application, you may want to hand write the bottlenecks in assembly. And you will get better performance trying to first use the registers as much as possible, and then the stack, and then the heap when you have to. Also, you will want to use vectorized cpu instructions as much as possible.

But if you don't have a good reason to not allow compiler optimizations (not sure exactly what cases you need to do this, besides choosing -O1, or -O2 instead of -O3 ), you should consider trivial access through functions to be a non-performance issue.
 
  • #27
FactChecker said:
I have seen large structures copied one member at a time from one structure to another using get and put functions. They can easily take orders of magnitudes longer than accessing the same data in global static memory. And, depending on how much data is being copied around, the programs can be unusable. Correcting the problem can require a complete rewrite of the code.

The solution here is not using a global variable, it's passing and returning by address instead of value.
 
  • #28
Jarvis323 said:
The solution here is not using a global variable, it's passing and returning by address instead of value.
That's a good point but that gives up control of how the data is accessed. The point of the get/put methods was to keep control within the class. Once you can access a large structure using a pointer, it doesn't make much difference if it is local or global.
 
  • #29
FactChecker said:
That's a good point but that gives up control of how the data is accessed. The point of the get/put methods was to keep control within the class. Once you can access a large structure using a pointer, it doesn't make much difference if it is local or global.

You can return in a read only form. If you need to modify it from outside then it's likely a badly designed code. Either way, it still makes no difference whether the access is through functions in terms of performance. If you are talking about setting, then through a function still gives you some control because you can make some enforceable rules how this happens. Additionally, you know the one avenue where this can be change, and you can easily isolate a problem related to it when debugging.
 
  • #30
The original question was about local versus global (or static) variables. Some variables should be global, usually variables used for communication and synchronization between threads and/or processes. In these cases, trying to pass a variable to every function that needs access to the global variable adds overhead in terms of maintenance and/or performance.

The other issue brought up here is encapsulation, including get / set methods. I have a different opinion about this, as I consider this type of encapsulation as unneeded overhead, again both for maintenance and performance. It's rare that a changing the implementation for a class member (say a change from integer to double) won't impact all the code that accesses the member along with code that works with the values associated with that member, regardless of encapsulation. The other issue is "protecting" a class member, but I don't see a need for protection since normally the members of a programming team can be trusted, and code reviews can be asked for if something is complicated. In my experience, in house or outside tools have been used to track down every source file reference to any variable or class member, to use with a tool to track when the files are updated to handle a change in the way a variable is used or implemented, so that nothing is skipped. One easy way to ensure this is to make a slight name change to the variable.
 
  • Like
Likes Silicon Waffle
  • #31
From all of the replies it appears that the answer is completely contextual - that we can all hopefully agree on. Bottom line in the most general sense is to program to the language's standard and more importantly to your company/industry's standard.
 
  • #32
Coming from a hobbyist programmer.. I learned to code with NO examples except for the "help" section of Qbasic.. it had NO guidelines on how to code properly.. .Somehow, very surprisingly, I wrote some pretty impressive programs which didn't even use subs and functions!.. Just a WHOLE WHACK of global variables, and lots and lots of "GOTO" statements.
Then I started playing with VB6 and VB.net, and had to try to understand other people's code, nevermind code I had written a couple months earlier.

It took years, and I'm not there yet, but I have figured out how to MOSTLY eliminate global variables, use functions, classes, etc and find alternatives to "goto".

For me, there's something that I still will use global variables for.. things like an "abort" or "Cancel" flag variable that gets checked in a nested part of the program but set in the UI thread

It takes a bit of getting used to, but it is best to minimize global variables whenever possible.. There may be exceptions to the rule, but it's best to learn how to follow the rule before learning when it's correct to break it.
 

1. What are local variables and global variables?

Local variables are variables declared within a specific function or block of code and can only be accessed within that function or block. Global variables, on the other hand, are declared outside of any function or block and can be accessed from anywhere in the code.

2. What are the advantages of using local variables over global variables?

Local variables help to keep the code organized and avoid naming conflicts. They also improve the efficiency of the code as they are only stored in memory when the function or block is executed.

3. When should I use local variables over global variables?

Local variables should be used when the value is only needed within a specific function or block of code. This helps to avoid cluttering the global namespace and reduces the chances of errors.

4. Are there any situations where global variables are preferred over local variables?

Global variables may be preferred in situations where the value needs to be accessed from multiple functions or blocks of code. However, this should be used sparingly as it can make the code less organized and harder to debug.

5. What are some best practices for using local and global variables?

Some best practices for using local and global variables include giving variables meaningful and descriptive names, limiting the use of global variables, and avoiding naming conflicts by using unique variable names. It is also important to keep the scope of variables in mind and use them appropriately.

Similar threads

  • Programming and Computer Science
Replies
4
Views
1K
  • Programming and Computer Science
Replies
18
Views
8K
  • Quantum Interpretations and Foundations
2
Replies
37
Views
1K
  • Programming and Computer Science
2
Replies
36
Views
2K
  • High Energy, Nuclear, Particle Physics
Replies
4
Views
3K
  • Other Physics Topics
Replies
1
Views
3K
  • Special and General Relativity
Replies
5
Views
1K
Replies
7
Views
5K
Replies
80
Views
4K
Replies
6
Views
1K
Back
Top