105

Can someone explain when you're supposed to use the static keyword before global variables or constants defined in header files?

For example, lets say I have a header file with the line:

const float kGameSpriteWidth = 12.0f;

Should this have static in front of const or not? What are some best practices for using static?

Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271
Matt
  • 1,710
  • 3
  • 14
  • 15
  • Note that in C++, ```static``` is implied (i.e. it's ```static``` by default) for all global namespace ```const```-qualified variables, though I would recommend qualifying it as ```static``` regardless so that intent is made clear. – abc Feb 22 '20 at 20:03
  • See also [How do I use `extern` to share variables between source files?](https://stackoverflow.com/q/1433204/15168) The answers there explain how to share values — and a key part of the is using a header to declare (but _not_ define) variables that are shared. If you don't have a header to put the declaration in, the variable definition should be static. If you do have a header for it, include the header both where the variable is defined (that will be one source file only) and where it is used (could be many source files). – Jonathan Leffler May 02 '20 at 22:55

8 Answers8

154

You should not define global variables in header files. You should define them in .c source file.

  • If global variable is to be visible within only one .c file, you should declare it static.

  • If global variable is to be used across multiple .c files, you should not declare it static. Instead you should declare it extern in header file included by all .c files that need it.

Example:

  • example.h

    extern int global_foo;
    
  • foo.c

    #include "example.h"
    
    int global_foo = 0;
    static int local_foo = 0;
    
    int foo_function()
    {
       /* sees: global_foo and local_foo
          cannot see: local_bar  */
       return 0;
    }
    
  • bar.c

    #include "example.h"
    
    static int local_bar = 0;
    static int local_foo = 0;
    
    int bar_function()
    {
        /* sees: global_foo, local_bar */
        /* sees also local_foo, but it's not the same local_foo as in foo.c
           it's another variable which happen to have the same name.
           this function cannot access local_foo defined in foo.c
        */
        return 0;
    }
    
Tomek Szpakowicz
  • 14,063
  • 3
  • 33
  • 55
  • 4
    I think you've missed the point. This is a const float, there's nothing wrong with defining it static const in a header file, and having a different copy of it in each translation unit. But most people would just use a #define to a literal. – Steve Jessop Dec 06 '09 at 22:43
  • 9
    Question was: "Can someone explain when you're supposed to use the static keyword before global variables or constants defined in header files?" Since OP seems to be beginner, I simply gave the most basic rule about defining global variables in C. As you have noticed yourself--you usually cannot do yourself harm using global _const_s in header file (in C, it's not so simple in C++). – Tomek Szpakowicz Dec 07 '09 at 06:29
  • After all, it's just compiler's enforcement. And after all and all, it's nothing but human's will... – smwikipedia Mar 30 '18 at 01:22
  • 1
    Is including example.h necessary in foo.c? – hammadian Jun 04 '18 at 16:37
  • @hammadian It is not necessary in this case. Still it is a good idea to include it. It gives compiler a chance to detect any discrepancies between declarations in h file and definitions in c file. – Tomek Szpakowicz Jun 06 '18 at 10:59
  • 1
    for the extern global_foo part it's basically the global_foo variable from file foo.c that is being called to the file example.h – imnotarobot Oct 12 '21 at 16:24
  • This answer is incorrect... There are times you want to have a variable declared in a header file (and even defined with a default value) and set the value independently within each source file that consumes the header. Extern is for when you want every consuming source file to share the same value across the application. – M.Kerr Aug 26 '22 at 19:36
  • @M.Kerr "Extern is for when you want every consuming source file to share the same value across the application." Isn't this the definition of a global variable? – Tomek Szpakowicz Nov 07 '22 at 13:35
  • @M.Kerr _"[...] a variable declared in a header file [...] and set the value independently within each source[...]"_ True. You can define a static variable in a header and have a separate instance in each compilation unit. But you should not: Suddenly by moving a function to another compilation unit, merging two compilation units etc. you can inadvertently change the behaviour of the code in a subtle way. And no unity build for you. Do you want to allow each client of your module to control its state independently? Make it explicit and pass it to your functions as a parameter. – Tomek Szpakowicz Nov 07 '22 at 13:42
66

static renders variable local to the file which is generally a good thing, see for example this Wikipedia entry.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • 16
    I don't think this has to do with "files", instead it has to do with "compilation modules". – Khaled Alshaya Dec 06 '09 at 21:09
  • 4
    If variable is not `extern` then it is not accessible from outside of the `C` file. Then what is the point of defining it as static? – alex May 16 '19 at 23:56
  • 2
    @alex A very good question. By default global variables are extern, but it's good practice to label it as such anyways. – Austin Salgat Dec 20 '19 at 05:11
  • 1
    @Arak to be precise, it has to do with "compilation units" - that's right the naming I believe. I know that question does not have C++ tag, but actual compilation modules came to new C++ standard so better not to confuse people. – Andrey Borisovich Jun 13 '21 at 22:50
31

Yes, use static

Always use static in .c files unless you need to reference the object from a different .c module.

Never use static in .h files, because you will create a different object every time it is included.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • the linker can't see that they are constants and optimize away all the different objects? – Trevor Hickey Aug 05 '15 at 18:25
  • But they are not constants, and it's important that the linker not accidentally merge private objects together simply because they have the same name. Linkers have no high level information at all, they just deal with symbols, bit strings, space, and references. Constants aren't visible to linkers at all, they just affect generated code during compilation. – DigitalRoss Aug 06 '15 at 17:01
  • 8
    Another way to say this is: the entire point of `static` is to *allow* the same name to be two different objects in two different modules. – DigitalRoss Apr 20 '16 at 23:31
10

Rule of thumb for header files:

  • declare the variable as extern int foo; and put a corresponding intialization in a single source file to get a modifiable value shared across translation units
  • use static const int foo = 42; to get a constant which can be inlined
Christoph
  • 164,997
  • 36
  • 182
  • 240
8

static before a global variable means that this variable is not accessible from outside the compilation module where it is defined.

E.g. imagine that you want to access a variable in another module:

foo.c

int var; // a global variable that can be accessed from another module
// static int var; means that var is local to the module only.
...

bar.c

extern int var; // use the variable in foo.c
...

Now if you declare var to be static you can't access it from anywhere but the module where foo.c is compiled into.

Note, that a module is the current source file, plus all included files. i.e. you have to compile those files separately, then link them together.

Khaled Alshaya
  • 94,250
  • 39
  • 176
  • 234
8

The static keyword is used in C to restrict the visibility of a function or variable to its translation unit. Translation unit is the ultimate input to a C compiler from which an object file is generated.

Check this: Linkage | Translation unit

Parag
  • 662
  • 9
  • 15
-1

The correct mechanism for C++ in anonymous namespaces. If you want something that is local to your file, you should use an anonymous namespace rather than the static modifier.

YesThatIsMyName
  • 1,585
  • 3
  • 23
  • 30
rmn
  • 2,386
  • 1
  • 14
  • 21
  • 1
    I think this answer is badly worded, too concise and off topic (although the OP does not specify that, the question is tagged C, not C++). – p4010 Nov 11 '19 at 14:46
-2

global static variables are initialized at compile-time unlike automatic

Captain Comic
  • 15,744
  • 43
  • 110
  • 148