views:

276

answers:

5

I wonder about the use of the static keyword as scope limiting for variables in a file, in C.

The standard way to build a C program as I see it is to:

  • have a bunch of c files defining functions and variables, possibly scope limited with static.
  • have a bunch of h files declaring the functions and possibly variables of the corresponding c file, for other c files to use. Private functions and variables are not published in the h file.
  • every c file is compiled separately to an o file.
  • all o files are linked together to an application file.

I see two reasons for declaring a gobal as static, if the variable is not published in the h file anyway:

  • one is for readability. Inform future readers including myself that a variable is not accessed in any other file.
  • the second is to prevent another c file from redeclaring the variable as extern. I suppose that the linker would dislike a variable being both extern and static. (I dislike the idea of a file redeclaring a variable owned by someone else as extern, is it ok practice?)

Any other reason?

Same goes for static functions. If the prototype is not published in the h file, other files may not use the function anyway, so why define it static at all? I can see the same two reasons, but no more.

+4  A: 

By declaring a variable static on file level (static within function has a different meaning) you forbid other units to access it, e.g. if you try to the variable use inside another unit (declared with extern), linker won't find this symbol.

qrdl
This is exactly one of the two reasons I mentioned: "the second is to prevent another c file from using the seemingly scope-limited global by redeclaring it as `extern`." And I wondered about the quality of such practice?
Gauthier
@Gaunthier So your post has an internal conflict then
qrdl
IMO, `static` has the same meaning in all three well-known uses (file variable, function variable, function) and that is: "this has limited scope and has a constant address throughout the program execution".
Gauthier
Well, in this sense meaning is the same, but purpose is different - `static` on file level controls visibility, `static` on function level controls persistence.
qrdl
If you declare something static in one compilation unit, you cannot redeclare it as extern in another compilation unit. They will be seen as different things. static serves also to prevent namespace pollution - e.g. you can have 2 compilation units contain a function named `sort` , and they will be treated as different things.
nos
@nos Exactly, so linker will complain about missing symbol
qrdl
@qrdl: I hope my post is clearer now.@nos: about namespace pollution, if two files contain functions with the same name, but those are not published in any h file, the separate compilation of the c file would work. The only problem is if a third file wouldn't know which of these two functions to call. But that is not a problem, since none of these are published in an h file. However if one of the files containing `sort` has published the header but the other file has not, I see your point.
Gauthier
@Gauthier So I've changed my post accordingly
qrdl
@qrdl: but your post is still the same as the second reason I mention: "prevent another c file from redeclaring the variable as extern.". I am looking for other reasons (sorry if that was not clear).
Gauthier
@Gauthier I was implying static functions - you don't have to care/worry about someone else named their function `sort` as well as the one you want in your compilaton unit is static However, if you have 2 non-static functions with the same name, it usually won't link , regardless of wether you declare it in a .h file or not (and if your linker still accepts it, you'll get undefined behavior)
nos
+1  A: 

If a global variable is declared static, the compiler can sometimes make better optimizations than if it were not. Because the compiler knows that the variable cannot be accessed from other source files, it can make better deductions about what your code is doing (such as "this function does not modify this variable"), which can sometimes cause it to generate faster code. Very few compilers/linkers can make these sorts of optimizations across different translation units.

Adam Rosenfield
+4  A: 

When you talk about informing other readers, consider the compiler itself as a reader. If a variable is declared static, that can affect the degree to which optimizations kick in.

Redefining a static variable as extern is impossible, but the compiler will (as usual) give you enough rope to hang yourself.

If I write static int foo; in one file and int foo; in another, they are considered different variables, despite having the same name and type - the compiler will not complain but you will probably get very confused later trying to read and/or debug the code. (If I write extern int foo; in the second case, that will fail to link unless I declare a non-static int foo; somewhere else.)

Global variables rarely appear in header files, but when they do they should be declared extern. If not, depending on your compiler, you risk that every source file which includes that header will declare its own copy of the variable: at best this will cause a link failure (multiply-defined symbol) and at worst several confusing cases of overshadowing.

crazyscot
Interesting. I understand that this "extern global in header file" still needs definition in a c file, since extern in the h file makes it a mere declaration.
Gauthier
You are correct.
crazyscot
+1  A: 

When you declare a static function the call to the function is a "near call" and in theory it performs better than a "far call". You can google for more information. This is what I found with a simple google search.

Iulian Şerbănoiu
Also interesting, although platform dependent (my target has only one CALL instruction to absolute, and no far/near).
Gauthier
e.g. gcc can switch calling convention(to something faster) for static functions on many platforms.
nos
A: 

My favorite usage of static is being able to store methods that I wont have to Inject or create an object to use, the way I see it is, Private Static Methods are always useful, where public static you have to put some more time in thinking of what it is your doing to avoid what crazyscot defined as, getting your self too much rope and accidentally hanging ones self!

I like to keep a folder for Helper classes for most of my projects that mainly consist of static methods to do things quickly and efficiently on the fly, no objects needed!

Gnostus
Question is about C, not C++. In C there are no classes, no methods, and no private members. Moreover, in C++ there is a difference in static functions and static methods.
el.pescado
Oops! I realize I definitely misread the question.
Gnostus