When can a global variable be used in C?

Apparently, there are many different opinions, ranging from " Never! Always encapsulate (even if it's with a simple macro!) " To " It doesn't really matter - use them when it's more convenient than not. "

So.

Specific, specific reasons (preferably with an example)

  • Why global variables are dangerous
  • When to use global variables instead of alternatives
  • What alternatives exist for those who are tempted to misuse global variables

While this is subjective, I will choose one answer (which for me best represents the love / hate relationship that every developer should have with globals), and the community will vote for them a little lower.

I consider it important that newcomers have such a link, but please do not clutter it if there is another answer that is essentially similar to yours - add a comment or edit someone else.

-Adam

+36
c global-variables
Oct 06 '08 at 20:43
source share
15 answers

Variables should always have a smaller scope. The argument in this is that every time you increase the scope, you have more code that potentially modifies the variable, so the solution is difficult.

Thus, it is clear that avoiding the use of global variables is preferred if design and implementation allow this. Because of this, I prefer not to use global variables unless they are really needed.

I can not agree with the statement "never", like any other concept. Global variables are a tool that should be used when necessary. I would rather use global variables than use some artificial constructs (like passing pointers) that only mask the real intent. Good examples that use global variables are singleton pattern implementations or case access in embedded systems.

About how to actually detect the overuse of global variables: inspection, inspection, inspection. Whenever I see a global variable, I have to ask myself: is this really necessary in the global field?

+39
Oct. 06 '08 at
source share

The only way to make global variables work is to give them names that guarantee that they are unique.

This name usually has a prefix associated with some β€œmodule” or set of functions for which the global variable is particularly focused or makes sense.

This means that the variable "belongs" to these functions - this is part of them. Indeed, the global can usually be "wrapped" with a small function that combines with other functions - in the same .h file name prefix.

Bonus

When you do this, all of a sudden, it is no longer global. Now it is part of a module of related functions.

It can always be done. With a little thought, each former global variable can be assigned to some collection of functions allocated to a specific .h file, and isolated by functions that allow you to change the variable without breaking it.

Instead of saying "never use global variables", you can say "assign duties to a global variable for some module where it makes the most sense."

+15
Oct 06 '08 at 22:15
source share

Consider this koan: "if the area is narrow enough, everything is global."

At this age, you still really need to write a very fast utility to do a one-time job.

In such cases, the energy needed to create safe access to the variables is greater than the energy saved by debugging problems in such a small utility.

This is the only time I can think about where global variables are wise, and this is relatively rare. Useful new programs are so small that they can be completely held in the brain. Short-term memory is becoming increasingly rare, but they still exist.

In fact, I could safely say that if the program is not so small, then global variables should be illegal.

  • If the variable never changes, then it is a constant, not a variable.
  • If a variable requires universal access, then there must be two subprograms to receive and configure it, and they must be synchronized.
  • If the program starts working with a small one and maybe more later, then enter the code as if the program was large today and canceled global variables. Not all programs will grow! (Although, of course, this suggests that the programmer is sometimes ready to delete the code.)
+10
Oct 06 '08 at 21:35
source share

Global variables in C are useful to make the code more readable if the variable is required by several methods (instead of passing the variable to each method). However, they are dangerous because all locations have the ability to change this variable, making tracking errors difficult. If you must use a global variable, always make sure that it changes in only one way and that all other users use this method. This will greatly facilitate debugging problems associated with changes to this variable.

+7
Oct 06 '08 at 20:44
source share

If thread-safe code doesn't bother you : use them wherever it makes sense, in other words wherever it makes sense to express something as a global state.

When your code can be multi-threaded : avoid at all costs. Abstract global variables in work queues or some other thread-safe structure or, if absolutely necessary, wrap them in locks, bearing in mind that these are probably bottlenecks in the program.

+5
Oct 06 '08 at 21:29
source share

I came from the camp "never" until I started working in the defense industry. There are some industry standards that require software to use global variables instead of dynamic ones (malloc in C memory). I need to rethink my approach to dynamic memory allocation for some of the projects I'm working on. If you can protect global memory with appropriate semaphores, threads, etc., then this may be an acceptable approach to managing your memory.

+4
Oct 06 '08 at
source share

Code complexity is not the only problem optimization. For many applications, performance optimization has a much higher priority. But more importantly, the use of global variables can significantly reduce the degree of code complexity in many situations. There are many, possibly specialized situations in which global variables are not only an acceptable solution, but also preferred. My favorite specialized example is their use to provide communication between the main application stream and the audio callback function, which works in a real-time stream.

It is unacceptable to assume that global variables are obligations in multi-threaded applications, since any variable, regardless of scope, is a potential liability if it is subject to change by more than one thread.

Using global variables sparingly. Data structures should be used whenever possible to organize and isolate the use of the global namespace.

A variable scope provides programmers with very useful protection - but it can be worth it. Today I started writing about global variables because I am an experienced Objective-C programmer who often gives up on object-oriented data access barriers. I would say that anti-glottular fanaticism comes mainly from younger theory-oriented programmers who experience mostly object-oriented APIs in isolation without the deep practical experience of level APIs and their interactions in application development. But I have to admit that I'm upset when providers use the namespace sluggishly. Several Linux distributions had, for example, β€œPI” and β€œTWOPI,” for example, which severely violated my personal code.

+3
Dec 03 '10 at 8:55
source share

You need to consider in what context the global variable will be used. In the future you will want to duplicate this code.

For example, if you use a socket in the system to access a resource. In the future, you will want to access more than one of these resources, if the answer is yes, I would stay away from the globals, so the main refactor is not needed.

+2
Oct 06 '08 at 20:55
source share

It is a tool like any other, usually abusing, but I do not think they are evil.

For example, I have a program that really acts like an online database. Data is stored in memory, but other programs can manipulate it. There are internal procedures that act as stored procedures and triggers in the database.

This program contains hundreds of global variables, but if you think about it, then what is a database, but a huge number of global variables.

This program has been used for about ten years through many versions, and it has never been a problem, and I would have done it in a minute.

I acknowledge that in this case, global vars are objects that have methods used to change the state of an object. Therefore, keeping track of who changed the object during debugging is not a problem, since I can always set a breakpoint in a routine that changes the state of the object. Or even simpler, I just turned on a built-in log that records changes.

+1
Oct. 06 '08 at 20:50
source share

Global variables should be used when several functions need to access data or write them to an object. For example, if you need to transfer data or a link to several functions, such as a single log file, connection pool or a hardware link, which must be accessed through the application. This prevents very long function declarations and large duplicate data distributions.

Usually you should not use global variables if it is absolutely necessary, because global variables are only cleared when explicitly told to do this, or your program terminates. If you are using a multi-threaded application, they can simultaneously write several variables into one variable. If you have an error, tracking this error can be more complicated because you do not know which function is changing this variable. You also face the problem of name conflicts if you do not use a naming convention that explicitly gives global variables a unique name.

+1
Oct 06 '08 at 21:05
source share

When you declare constants.

+1
06 Oct '08 at 21:20
source share

I can think of several reasons:

debugging / testing (warning - did not check this code):

 #include <stdio.h> #define MAX_INPUT 46 int runs=0; int fib1(int n){ ++runs; return n>2?fib1(n-1)+fib1(n-2):1; }; int fib2(int n,int *cache,int *len){ ++runs; if(n<=2){ if(*len==2) return 1; *len=2; return cache[0]=cache[1]=1; }else if(*len>=n) return cache[n-1]; else{ if(*len!=n-1) fib2(n-1,cache,len); *len=n; return cache[n-1]=cache[n-2]+cache[n-3]; }; }; int main(){ int n; int cache[MAX_INPUT]; int len=0; scanf("%i",&n); if(!n||n>MAX_INPUT) return 0; printf("fib1(%i)==%i",n,fib1(n)); printf(", %i run(s)\n",runs); runs=0; printf("fib2(%i)==%i",n,fib2(n,&cache,&len)); printf(", %i run(s)\n",runs); main(); }; 

I used moving variables for fib2, but this is another scenario in which global variables (pure mathematical functions that should store data to avoid them forever) can be useful.

programs used only once (for example, for a competition), or when development time needs to be reduced

globals are useful as typed constants, where a function somewhere requires * int instead of int.

I usually avoid global bindings if I intend to use the program for more than one day.

+1
Feb 19 2018-11-18T00:
source share
  • When not to use: Global variables are dangerous because the only way to find out how the global variable has changed is to trace all the source code inside the .c file in which they are declared (or, all .c files, if it is also extern). If your code is defective, you need to search the entire source file (s) to see which functions change it and when. This is a nightmare for debugging when it goes wrong. We often take for granted the ingenuity of the concept of local variables that gracefully go out of scope - it's easy to trace
  • When to use: Global variables should be used when its use is not too disguised, and where the cost of using local variables is excessively complex to the point that it compromises readability. By this, I mean the need to add an additional parameter for the function arguments and return and pass the pointers around, among other things. Three classic examples: when I use pop and push stack - this is shared between functions. Of course, I could use local variables, but then I would have to pass pointers as an additional parameter. A second classic example can be found in K & R's C Programming Language, where they define the getch () and ungetch () functions that share a global character buffer array. Once again, we do not need to make it global, but the added complexity is worth it when it is quite difficult to ruin the use of the buffer? The third example is what you will find in the built-in space among Arduino lovers. Many of the functions in the main function of the loop all use the millis () function, which is the instantaneous response time of the function. Since the clock speed is not infinite, millis () will differ within the same cycle. To make it permanent, take a snapshot of the time before each cycle and save it in a global variable. Now the snapshot will be the same as when accessing many functions.
  • Alternatives: Not so much. Adhere to local coverage as much as possible, especially at the beginning of the project, and not vice versa. As the project grows, and if you feel that complexity can be reduced using global variables, do it, but only if it meets the requirements of paragraph 2. And remember that using a local area and more complex code is a lesser evil compared to irresponsible use of global variables.
+1
Jan 13 '17 at 21:57
source share

I'm here in the never camp; if you need a global variable, at least use a singleton pattern . In this way, you are reaping the benefits of a lazy instance, and you are not cluttering up the global namespace.

0
Oct 06 '08 at 20:49
source share

Global constants are useful - you get more type safety than preprocessor macros, and it is just as easy to change the value if you decide what you need.

Global variables have some uses, for example, if the operation of many parts of the program depends on the specific state in the final machine. As long as you limit the number of places that CHANGE variable tracking errors associated with this is not so bad.

Global variables become dangerous almost immediately after creating multiple threads. In this case, you really need to limit the scope (at best) to the global file (by declaring it static) with the getter / setter methods that protect it from multiple access if this could be dangerous.

0
Jan 21 '09 at 2:23
source share



All Articles