As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Global variables are generally considered to be a poor programming practice
In C, are static variables (i.e with module (file) scope) considered OK?
My thought was that member variables in an object oriented language cannot be much less dangerous than static variables in C and member variables seem to be considered to be a good thing.
I'm tiring of passing parameters through multiple functions and can see the attraction of static variables for this, especially if they are const.
But I'm keen to know if this is frowned upon - and also whether there is really any difference in level of programming naughtiness between a big object with a member variable used in several of its methods and a C file containing a few functions that utilize a static variable?
Static (file-scope) variables in C are similar to static member variables in C++.
Any use of non-const static variables for communicating between functions makes those functions nonreentrant and thread-unsafe. Thus, in general it would be preferable to pass the information via parameters.
A better analogue for non-static member variables is a struct member. Just collect your "member variables" in a struct and pass that struct as a "this" parameter.
The big difference is: with member variables you can have multiple objects and each has its own member variable. With module scope static variables you have exactly one instance of the variable.
If you want to compare module level static variables and static class member variables then there is no real big difference. Both are instantiated exactly once, only the scope and access rules are different.
One of the big disadvantage of static variable is "side-effects", ie when the result of a function doesn't only depends of the input parameters which makes testing and debugging harder .
A function without side effect is much easier to test because you can assume that every time you call a function with the same set of parameters you can expect the same result.
If you have a bug, you can check then if the result is correct accordingly to the input parameters. If then you realize the input parameters are wrong, then you can track in your code where/who as the parameters wrongly. If your function depends on a static variable and the static variables doesn't have the expected value , how do you track/find why and how it changes ?
So, if you want to use constant, then use proper constant (#DEFINE) or group your parameters into a structure and try avoid static variable as much as possible.
(at least #DEFINE value won't get corrupted in memory)
Static variables are perhaps marginally better than globals, but not much. Being not as evil as global variables is not much of a commendation however!
When you have multiple threads or reentrant functions then they do not suffice. What's more using them as parameter passing mechanism will lead to code that is very hard to read and maintain. There are uses for static variables but I'd never use them for parameter passing. In some cases it can be better collecting parameters into a struct to be passed around.
You can use global or static variables, but use them with care. I'm not sure that module-wide static variables are much better than global ones.
In particular, having more than a dozen global variables in even a big program is probably poor taste (but that happens).
And you might prefer to group your static or global data in larger struct-s.
In the context you're trying to use them, module variables are probably a bad idea. The nice thing about passing everything by parameters is so that it's hard to get out-of-sync with your method calls. Each method does something and passes some component of that off to another method, so it's easy to trace - the variables are only live during the method call. It gets more difficult to debug if the variables exist somewhere else - things like using a stale variable go from impossible to rather likely.
Static variables are typically used as flags - a common one being a boolean that you set to change the mode of the whole module in a subtle way (a quasi-builtin one being DEBUG).
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
While I know what's the difference between local and global variables I just can't understand if it's important at all, especially when talking about local variables inside the main function.
For example what's the difference here except that we can't use the testvar in the second case in other functions?
First Case:
#include <stdio.h>
int testvar;
Second Case:
#include <stdio.h>
int main(void){
int testvar;
}
Edit: What I mean is that if I am going only to use a variable inside main then does declaring it as global have any advantage Or that in this specefic case nothing different at all?
Good practice in software engineerIng is to limit the scope of names to where they are used. If testvar is declared outside of main, then it is visible to code outside main. This exposes it to bugs in which some other code uses testvar when it was intended to use some other object (either another object with a different name that was mistyped or an object with the same name, but a different instance of it was desired). Additionally, because it is declared with int testvar; and not static int testvar;, it will be linked with other objects named testvar in other modules. This is a serious problem—it happens that one author of some routines used some name like AmountOfMemory for their own purposes and another author of other routines used the same name for their own purposes, and both pieces of code work separately, but, when linked into the same program, they break. For this reason, good code avoids global variables.
If testvar is declared inside main, none of those errors can occur. The probability of writing a good program is increased. Thus, if testvar is not needed (by name) outside of main, declaring it inside main is preferable.
There is also an issue of lifetime. Similarly to scope (where a name is visible), we prefer to limit lifetime (when an object exists). In the case of an object defined inside main, its lifetime is effectively the same as an object declared outside of any function—it will exist for the duration of program execution. So lifetime is not a great concern here. However, there is a situation in which it is. In C, it is permissible to call main inside the function. This is rarely used. However, if it is used and if testvar is defined outside main, there will be only one instance of it, and all executions of main will share them. If testvar is defined inside main, each execution of main will have its own instance of testvar, separate from the others.
Another difference between objects defined inside functions and those defined outside functions is that C automatically initializes objects defined outside functions to zero by default. This however would not affect the choice of where to define the object as an explicit initialization can be provided as desired.
"While I know what's the difference between local and global variables I just can't understand if it's important at all"
For me, when learning C, I felt like I didn't really understand the difference between local and global variables, until I understood why it's important.
Eric Postpischil's answer about scope and lifetime says it all. It's not a mere difference in how and where you can use the variables; it's the broader implications about what can happen because of that access.
So don't think in terms of "if I am going only to use a variable inside main()"; think in terms of encapsulation, modularity, interfaces, and shared code. I would go so far as to suggest never using global variables; any time you are tempted to do so, it will be worth the effort to find another way to accomplish what you are trying to do. Your future self will thank you for solid programming habits you foster now.
For example what's the difference here except that we can't use the testvar in the second case in other functions?
From a C standard point of view that is actually the main difference (see later for another differance). If you define the variable inside main it has automatic storage duration and is only accessible using its variable name inside main. If you define the variable outside main it has static storage duration and can be accessed using its variable name from anywhere in the code.
One difference is that variables with static storage duration are default initialized while variables with automatic storage duration are left uninitialized. So in your first example testvar will be initialized to zero while it is uninitialized in the second example.
This question already has an answer here:
What is the purpose of static keyword in array parameter of function like "char s[static 10]"?
(1 answer)
Closed 8 years ago.
As we know, the keyword static has multiple meanings in C. C99 added the possibility of legally writing
void foo (int arr[static 50])
{
// ...
}
which adds to the confusion, and C++ has static member variables and functions.
This would not be so troublesome if all the uses could be connected in some way, but I find it hard to find that link for some of the cases. Particularly why the static keyword should be used to modify visibility (linkage), or what on earth it's got to do with an array's minimum amount of elements.
So is there a historical reason for the abuse of the static keyword, or is there a secret link under the hood that connects all of its uses?
Adding new keywords to a language breaks backwards compatibility. So static gets used where its use might possibly mean something ( int arr[static 50] vs int arr[auto 50] or int arr[extern 50] ) and cannot syntactically appear in that location based its use in previous versions.
Though in that case adding a not_less_than context sensitive keyword in that position would not break previous code, it would add another keyword (so simple text editors which are keyword aware but not syntax aware would not know whether or not it is a keyword), and break the 'keywords are not context sensitive' simplification made in C.
There is a very simple way of remembering of all 3 C++ meanings of static I'm aware of. static means "pretty much like global variable/function but only available directly in scope of..."
"...this file" if it is in global scope.
"...this function" if it is in a function (including member functions). Note that if you make classes and lambdas in a function, they are still in this scope. Lambda with an empty capture can access static variable of its "parent" function.
"...this class" if it is in a class (including those declared with struct). This case is slightly different as you can access the variable/function through an object or by prefixing, but this is a little like asking the class or its object to provide you access to it, and it in fact can be denied (with private). So the access isn't "direct".
In case of the presented C99 array syntax, this is something completely different and I assume it was there to not introduce new keywords, as others suggest.
static's original meaning in C++ is actually deprecated, replaced with unnamed namespaces. The only way static is actually used in current C++ code is to be non-member.
I think the reasons are different for the different usages that this keyword has. If we take the function scope and file scope use as of classical C for granted (they are at least similar concepts) the first addition off topic is the static in C++ to name a global member of a class.
I guess here the shortcut was just that "static" and "global" seemed to be close enough and early C++ was very careful not to introduce new keywords that would break existing code. So they took an existing one that could not appear in that context.
For the C99 add-on for array parameters things are different, I think, because static is not the only addition, here. You may also have type qualifiers (const and volatile) that qualify the implicit pointer:
void toto1(char str[const 5]);
void toto2(char*const str);
define compatible prototypes. I can only speculate that the choice of the storage class specifier static for the purpose that you mention (minimum length of the array) was seen as a natural extension of that syntax. Also probably it easily proved that this use was compatible with the rest of language, by arguing where a type qualifier may be used to extend the language, a storage class specifier can't do much harm.
A camel is a horse designed by committee.
http://en.wikipedia.org/wiki/Design_by_committee
ADDED:
Committee members involved in the design are conservative, and are more interested in not breaking existing C++ code than the potential elegance of new code.
There might be another question like this on stack but I am not completely sure. So on to my question. My professor told everyone, "NEVER USE GLOBAL VARIABLES". But she said that static variables are allowed as long as you give a good enough reason. So my question is, under her criteria, is a static variable declared at the global level ok?
Unfortunately static has two meanings in C. When applied to a global variable, it means that the visibility of this symbol is in the file scope. When applied to a local variable, it means that this variable retains its value between calls (i.e., it's not really a local variable). Your professor is referring to the latter, not the former, when she says they are allowed.
There are times when global variables are useful. Consider stderr: it would be a pain to have to define it in every file you needed to use it in; it is sensibly defined as a global variable.
There are times when it is sensible to store a variable at file scope without external linkage (which you do using static as part of the definition of the variable, outside the scope of any function). For example, if you have a suite of functions which need to share some state but the API does not pass a handle back to the calling code (so there isn't an analogue of open and close — or create and destroy), then one or more static variables at file scope make sense.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I have started programming in C and in general I'm looking for "best practices" to structure my code.
Having mainly used object oriented languages before, I started to adopt some practices from these languages.
My concrete question is: Is this code considered "acceptable" C code or am I running into a common trap for people trying to use encapsulation in C?
// A.h
void setValue(int);
int getValue();
// A.c
#include "A.h"
int my_private_value;
void setValue(int v)
{
my_private_value = v;
}
int getValue(void)
{
return my_private_value;
}
To be pedantic: there are no global variables in C. Variables have scope, storage duration and linkage. For none of these there exists a 'global' qualification.
So what is going on, then? Your
int my_private_value;
is a variable with with file scope and external linkage (and static storage duration). This type of linkage means it can be referenced from any other file that has an extern int my_private_value declaration in scope. To avoid this, the variable must have internal linkage. To declare a variable with internal linkage, use the static keyword:
static int my_private_value;
So, if you wanna sound like a professional, whenever you are tempted to utter 'global variable', take a deep breath and speak the words object with file scope and external linkage. That'll make you shine in all C interviews :-)
Should somebody question your wisdom about the lack of "global" variables, you can even prove it to them. Global variables are in scope everywhere, right? But in C, the scope of an object starts not until its declaration. The lack of a truly global variable makes it impossible to forward reference a variable like in
int *foo = &bar; /* Doesn't work in C: bar is not (yet) in scope. */
int bar = 42;
It does work when you swap the two lines.
The only change I would make to your code is how my_private_value gets defined. I would define it as:
static int my_private_value;
This prevents external code modules from declaring extern int my_private_value; and then accessing it directly.
This is OK, but you need to make the variable static so that it has internal linkage; the way it is now, code in other files will be able to directly access it. See this for more information on linkage and how it affects the accessibility of variables, or this question that deals with the same matter.
For the access and availability of the variable, others have already answered, but generally I'd say that you'd have to have good reasons for such a kind of interface. It does reduce the potential of the compiler to optimize the access to the object.
What is not acceptable in C is this declaration:
int getValue();
which in C isn't a prototype. It declares a function that may receive an unspecified number of arguments. Instead, use:
int getValue(void);
I've seen this being done in C before and there's nothing wrong with it until you 1. don't want to be thread-safe (which you do want, in fact) and make the global variable static and not expose it through a header file. That said, using global vaiables is bad practice and should be avoided if possible.
It doesn't seem like it would be too hard to implement in assembly.
gcc also has a flag (-fnested-functions) to enable their use.
It turns out they're not actually all that easy to implement properly.
Should an internal function have access to the containing scope's variables?
If not, there's no point in nesting it; just make it static (to limit visibility to the translation unit it's in) and add a comment saying "This is a helper function used only by myfunc()".
If you want access to the containing scope's variables, though, you're basically forcing it to generate closures (the alternative is restricting what you can do with nested functions enough to make them useless).
I think GCC actually handles this by generating (at runtime) a unique thunk for every invocation of the containing function, that sets up a context pointer and then calls the nested function. This ends up being a rather Icky hack, and something that some perfectly reasonable implementations can't do (for example, on a system that forbids execution of writable memory - which a lot of modern OSs do for security reasons).
The only reasonable way to make it work in general is to force all function pointers to carry around a hidden context argument, and all functions to accept it (because in the general case you don't know when you call it whether it's a closure or an unclosed function). This is inappropriate to require in C for both technical and cultural reasons, so we're stuck with the option of either using explicit context pointers to fake a closure instead of nesting functions, or using a higher-level language that has the infrastructure needed to do it properly.
I'd like to quote something from the BDFL (Guido van Rossum):
This is because nested function definitions don't have access to the
local variables of the surrounding block -- only to the globals of the
containing module. This is done so that lookup of globals doesn't
have to walk a chain of dictionaries -- as in C, there are just two
nested scopes: locals and globals (and beyond this, built-ins).
Therefore, nested functions have only a limited use. This was a
deliberate decision, based upon experience with languages allowing
arbitraries nesting such as Pascal and both Algols -- code with too
many nested scopes is about as readable as code with too many GOTOs.
Emphasis is mine.
I believe he was referring to nested scope in Python (and as David points out in the comments, this was from 1993, and Python does support fully nested functions now) -- but I think the statement still applies.
The other part of it could have been closures.
If you have a function like this C-like code:
(*int()) foo() {
int x = 5;
int bar() {
x = x + 1;
return x;
}
return &bar;
}
If you use bar in a callback of some sort, what happens with x? This is well-defined in many newer, higher-level languages, but AFAIK there's no well-defined way to track that x in C -- does bar return 6 every time, or do successive calls to bar return incrementing values? That could have potentially added a whole new layer of complication to C's relatively simple definition.
See C FAQ 20.24 and the GCC manual for potential problems:
If you try to call the nested function
through its address after the
containing function has exited, all
hell will break loose. If you try to
call it after a containing scope level
has exited, and if it refers to some
of the variables that are no longer in
scope, you may be lucky, but it's not
wise to take the risk. If, however,
the nested function does not refer to
anything that has gone out of scope,
you should be safe.
This is not really more severe than some other problematic parts of the C standard, so I'd say the reasons are mostly historical (C99 isn't really that different from K&R C feature-wise).
There are some cases where nested functions with lexical scope might be useful (consider a recursive inner function which doesn't need extra stack space for the variables in the outer scope without the need for a static variable), but hopefully you can trust the compiler to correctly inline such functions, ie a solution with a seperate function will just be more verbose.
Nested functions are a very delicate thing. Will you make them closures? If not, then they have no advantage to regular functions, since they can't access any local variables. If they do, then what do you do to stack-allocated variables? You have to put them somewhere else so that if you call the nested function later, the variable is still there. This means they'll take memory, so you have to allocate room for them on the heap. With no GC, this means that the programmer is now in charge of cleaning up the functions. Etc... C# does this, but they have a GC, and it's a considerably newer language than C.
It also wouldn't be too hard to add members functions to structs but they are not in the standard either.
Features are not added to C standard based on soley whether or not they are easy to implement. It's a combination of many other factors including the point in time in which the standard was written and what was common / practical then.
One more reason: it is not at all clear that nested functions are valuable. Twenty-odd years ago I used to do large scale programming and maintenance in (VAX) Pascal. We had lots of old code that made heavy use of nested functions. At first, I thought this was way cool (compared to K&R C, which I had been working in before) and started doing it myself. After awhile, I decided it was a disaster, and stopped.
The problem was that a function could have a great many variables in scope, counting the variables of all the functions in which it was nested. (Some old code had ten levels of nesting; five was quite common, and until I changed my mind I coded a few of the latter myself.) Variables in the nesting stack could have the same names, so that "inner" function local variables could mask variables of the same name in more "outer" functions. A local variable of a function, that in C-like languages is totally private to it, could be modified by a call to a nested function. The set of possible combinations of this jazz was near infinite, and a nightmare to comprehend when reading code.
So, I started calling this programming construct "semi-global variables" instead of "nested functions", and telling other people working on the code that the only thing worse than a global variable was a semi-global variable, and please do not create any more. I would have banned it from the language, if I could. Sadly, there was no such option for the compiler...
ANSI C has been established for 20 years. Perhaps between 1983 and 1989 the committee may have discussed it in the light of the state of compiler technology at the time but if they did their reasoning is lost in dim and distant past.
I disagree with Dave Vandervies.
Defining a nested function is much better coding style than defining it in global scope, making it static and adding a comment saying "This is a helper function used only by myfunc()".
What if you needed a helper function for this helper function? Would you add a comment "This is a helper function for the first helper function used only by myfunc"? Where do you take the names from needed for all those functions without polluting the namespace completely?
How confusing can code be written?
But of course, there is the problem with how to deal with closuring, i.e. returning a pointer to a function that has access to variables defined in the function from which it is returned.
Either you don't allow references to local variables of the containing function in the contained one, and the nesting is just a scoping feature without much use, or you do. If you do, it is not a so simple feature: you have to be able to call a nested function from another one while accessing the correct data, and you also have to take into account recursive calls. That's not impossible -- techniques are well known for that and where well mastered when C was designed (Algol 60 had already the feature). But it complicates the run-time organization and the compiler and prevent a simple mapping to assembly language (a function pointer must carry on information about that; well there are alternatives such as the one gcc use). It was out of scope for the system implementation language C was designed to be.