What does "static" mean in C?

1,039,832

Solution 1

  1. A static variable inside a function keeps its value between invocations.
  2. A static global variable or a function is "seen" only in the file it's declared in

(1) is the more foreign topic if you're a newbie, so here's an example:

#include <stdio.h>

void foo()
{
    int a = 10;
    static int sa = 10;

    a += 5;
    sa += 5;

    printf("a = %d, sa = %d\n", a, sa);
}


int main()
{
    int i;

    for (i = 0; i < 10; ++i)
        foo();
}

This prints:

a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60

This is useful for cases where a function needs to keep some state between invocations, and you don't want to use global variables. Beware, however, this feature should be used very sparingly - it makes your code not thread-safe and harder to understand.

(2) Is used widely as an "access control" feature. If you have a .c file implementing some functionality, it usually exposes only a few "public" functions to users. The rest of its functions should be made static, so that the user won't be able to access them. This is encapsulation, a good practice.

Quoting Wikipedia:

In the C programming language, static is used with global variables and functions to set their scope to the containing file. In local variables, static is used to store the variable in the statically allocated memory instead of the automatically allocated memory. While the language does not dictate the implementation of either type of memory, statically allocated memory is typically reserved in data segment of the program at compile time, while the automatically allocated memory is normally implemented as a transient call stack.

And to answer your second question, it's not like in C#.

In C++, however, static is also used to define class attributes (shared between all objects of the same class) and methods. In C there are no classes, so this feature is irrelevant.

Solution 2

There is one more use not covered here, and that is as part of an array type declaration as an argument to a function:

int someFunction(char arg[static 10])
{
    ...
}

In this context, this specifies that arguments passed to this function must be an array of type char with at least 10 elements in it. For more info see my question here.

Solution 3

Short answer ... it depends.

  1. Static defined local variables do not lose their value between function calls. In other words they are global variables, but scoped to the local function they are defined in.

  2. Static global variables are not visible outside of the C file they are defined in.

  3. Static functions are not visible outside of the C file they are defined in.

Solution 4

Multi-file variable scope example

Here I illustrate how static affects the scope of function definitions across multiple files.

a.c

#include <stdio.h>

/*
Undefined behavior: already defined in main.
Binutils 2.24 gives an error and refuses to link.
https://stackoverflow.com/questions/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c
*/
/*int i = 0;*/

/* Works in GCC as an extension: https://stackoverflow.com/a/3692486/895245 */
/*int i;*/

/* OK: extern. Will use the one in main. */
extern int i;

/* OK: only visible to this file. */
static int si = 0;

void a() {
    i++;
    si++;
    puts("a()");
    printf("i = %d\n", i);
    printf("si = %d\n", si);
    puts("");
}

main.c

#include <stdio.h>

int i = 0;
static int si = 0;

void a();    

void m() {
    i++;
    si++;
    puts("m()");
    printf("i = %d\n", i);
    printf("si = %d\n", si);
    puts("");
}

int main() {
    m();
    m();
    a();
    a();
    return 0;
}

GitHub upstream.

Compile and run:

gcc -c a.c -o a.o
gcc -c main.c -o main.o
gcc -o main main.o a.o

Output:

m()
i = 1
si = 1

m()
i = 2
si = 2

a()
i = 3
si = 1

a()
i = 4
si = 2

Interpretation

  • there are two separate variables for si, one for each file
  • there is a single shared variable for i

As usual, the smaller the scope, the better, so always declare variables static if you can.

In C programming, files are often used to represent "classes", and static variables represent private static members of the class.

What standards say about it

C99 N1256 draft 6.7.1 "Storage-class specifiers" says that static is a "storage-class specifier".

6.2.2/3 "Linkages of identifiers" says static implies internal linkage:

If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.

and 6.2.2/2 says that internal linkage behaves like in our example:

In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function. Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function.

where "translation unit is a source file after preprocessing.

How GCC implements it for ELF (Linux)?

With the STB_LOCAL binding.

If we compile:

int i = 0;
static int si = 0;

and disassemble the symbol table with:

readelf -s main.o

the output contains:

Num:    Value          Size Type    Bind   Vis      Ndx Name
  5: 0000000000000004     4 OBJECT  LOCAL  DEFAULT    4 si
 10: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 i

so the binding is the only significant difference between them. Value is just their offset into the .bss section, so we expect it to differ.

STB_LOCAL is documented on the ELF spec at http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html:

STB_LOCAL Local symbols are not visible outside the object file containing their definition. Local symbols of the same name may exist in multiple files without interfering with each other

which makes it a perfect choice to represent static.

Variables without static are STB_GLOBAL, and the spec says:

When the link editor combines several relocatable object files, it does not allow multiple definitions of STB_GLOBAL symbols with the same name.

which is coherent with the link errors on multiple non static definitions.

If we crank up the optimization with -O3, the si symbol is removed entirely from the symbol table: it cannot be used from outside anyways. TODO why keep static variables on the symbol table at all when there is no optimization? Can they be used for anything? Maybe for debugging.

See also

C++ anonymous namespaces

In C++, you might want to use anonymous namespaces instead of static, which achieves a similar effect, but further hides type definitions: Unnamed/anonymous namespaces vs. static functions

Solution 5

It depends:

int foo()
{
   static int x;
   return ++x;
}

The function would return 1, 2, 3, etc. --- the variable is not on the stack.

a.c:

static int foo()
{
}

It means that this function has scope only in this file. So a.c and b.c can have different foo()s, and foo is not exposed to shared objects. So if you defined foo in a.c you couldn't access it from b.c or from any other places.

In most C libraries all "private" functions are static and most "public" are not.

Share:
1,039,832
Admin
Author by

Admin

Updated on July 19, 2022

Comments

  • Admin
    Admin almost 2 years

    I've seen the word static used in different places in C code; is this like a static function/class in C# (where the implementation is shared across objects)?

  • Eli Bendersky
    Eli Bendersky about 15 years
    Pax, the OP doesn't know about static, so you suggest plunging him into the difference between compilation units and files ? :-)
  • Eli Bendersky
    Eli Bendersky about 15 years
    A compilation unit is a single file the compiler sees. Your .c file may include other .c files, but after the preprocessor sorting out the includes, the compiler eventually sees just a single "compilation unit".
  • Eli Bendersky
    Eli Bendersky about 15 years
    David, if you're new to C, this issue shouldn't bother you at all. It doesn't bother 99.9% of C programmers anyway.
  • Johannes Schaub - litb
    Johannes Schaub - litb about 15 years
    so if you define a static in one header file that you include into a file, but in that file define the same static another time, it is an error, because the two definitions appear in the same translation unit.
  • ant2009
    ant2009 about 14 years
    This has got me thinking. Does the compilation unit consist of only its *.c file. For example, if I have a file called foo.c and a header called foo.h. Would the 2 of them consist of 1 compilation unit? Or would the foo.c be one complete compilation unit without the foo.h?
  • Eli Bendersky
    Eli Bendersky about 14 years
    @robUK: the compiler doesn't even know about the .h files - these are combined into the .c files in the pre-processor. So yes you can say that the .c file, with all the headers included into it, are a single compilation unit.
  • RoundPi
    RoundPi over 11 years
    +1 for mentioning x not on stack or heap. It's on the static memory space.
  • user1599964
    user1599964 over 11 years
    So does "static function" and "private function" means the same thing ? Similarly are "static global variables" and "private global variables" the same thing ?
  • user1599964
    user1599964 over 11 years
    So does "static function" and "private function" means the same thing ? Similarly are "static global variables" and "private global variables" the same thing ?
  • Eli Bendersky
    Eli Bendersky over 11 years
    @user1599964: there's no concept of "private" in C, per se. However, when functions and variables are made static in a C file, they are essentially private to this C file since they can't be accessed directly from other C files.
  • chris
    chris over 11 years
    This is about C. There is no private/public in C.
  • Tony Delroy
    Tony Delroy over 10 years
    I appreciate you're trying to clarify things, but your notion of compilers versus pre-processors is dated and confusing... modern "compilers" (as the word is generally used) internalise the preprocessor. It's accurate and simple enough to describe a translation or compilation unit as typically consisting of one .c implementation file and whatever headers it directly or indirectly #includes, and not bring preprocessor/compiler into it at all.
  • peterph
    peterph about 10 years
    @TonyD maybe it is confusing, but it is how the compilation works. It may typically be one .c and bunch of header files, but the devil is always in what is not typical.
  • Tony Delroy
    Tony Delroy about 10 years
    @peterph: then that can be addressed by saying "a translation unit consists of the source file(s) specified to the compiler on the command line, with each #include (direct or indirect) expanded in place". My point remains that describing "translation unit" adequately is less misleading or confusing than making statements like "A compilation unit is a single file the compiler sees." when there's not necessarily any single amalgamated "file" (on the disk, or even in the compiler's memory for that matter) involved. "static ... is "seen" only in the file it's declared in" - also misleading.
  • Miles Rout
    Miles Rout about 10 years
    @TonyD Sorry, but you're wrong. Preprocessing and compilation are totally different steps, and it's crucial to know how they differ.
  • Tony Delroy
    Tony Delroy about 10 years
    @MilesRout: Even sorrier that you're wrong about me being wrong - I agree with the rest of what you've said, but it doesn't relate to or contradict what I've said. Eli: "the compiler doesn't even know about the .h files - these are combined into the .c files in the pre-processor.", then me "modern "compilers" (as the word is generally used) internalise the preprocessor". I've talked about compiler not compilation.
  • Miles Rout
    Miles Rout about 10 years
    @TonyD The compiler does compilation. The preprocessor does preprocessing. Calling the toolchain 'the compiler' doesn't change what it is or what it does.
  • Palec
    Palec over 9 years
    Regarding the static function part, there is a good Q&A already: static function in C
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com about 9 years
    @user1599964 although there is no private in C, your analogy is good: static makes things "private" to a given file. And files in C often map to classes in C++.
  • Bondolin
    Bondolin about 9 years
    Might a functional definition to translation unit simply be the single .c file and all its direct/indirect includes which altogether produce a single .o file?
  • suprjami
    suprjami over 8 years
    I didn't think C had array arguments? Linus Torvalds rants angrily about people doing this.
  • TOMKA
    TOMKA over 8 years
    @jamieb: C doesn't have array arguments, but this specific syntax means that the function expects arg[0] through to arg[9] to have values (which also implies that the function does not accept a null pointer). Compilers could utilise this information somehow for optimisation, and static analysers can utilise this information to ensure that the function is never given a null pointer (or if it can tell, an array with fewer elements than specified).
  • Happy Green Kid Naps
    Happy Green Kid Naps over 8 years
    @Qix -- This was a new overloaded meaning given to static in C99. It is more than a decade and a half old, but not all compiler writers have embraced all of C99 features -- so C99 as a whole largely remains unknown.
  • Jon Wheelock
    Jon Wheelock about 8 years
    Why the same keyword is used in different senses? Once for storage type and other for limiting variable scope. They could not get other keywords!! C is unnecessarily made complex to understand by newbies.
  • RastaJedi
    RastaJedi about 8 years
    @suprjami I'm not 100% sure what you mean by "array arguments", but if you mean int arr[n];, then that is a VLA (variable-length array), which was added in C99. Is that what you meant?
  • hft
    hft over 7 years
    The two cases (1) and (2) are actually the same. It doesn't matter whether the "static int sa=10;" is "inside the function" or "outside the function". The compiled program is exactly the same regardless...
  • Bludzee
    Bludzee over 7 years
    @hft Wrong. For (1) sa is "seen" only inside the foo() function, whereas for (2) sa can be seen directly from main() or any other function in the same .c file.
  • hft
    hft over 7 years
    In the example given it doesn't matter. compile it both ways and see for yourself.
  • Honinbo Shusaku
    Honinbo Shusaku over 7 years
    As someone who has never used static in anything other than OO fashion, this helped me understand the use of state in Perl too
  • Eames
    Eames over 6 years
    I understand that the data is persistent, meaning that it won't be lost after each function call, but why doesn't static int var = 1; change the value back to one each time
  • DevReacc
    DevReacc over 6 years
    So when someone declares a global variable as static does that mean it can only be read by the file itself? Or do other files within the same directory also have access?
  • Yousha Aleayoub
    Yousha Aleayoub about 6 years
    @Gob00st static memory space? you meant "Data Segment"...?
  • Jens
    Jens almost 6 years
    There's a third storage class, register. Some people also make the case for a fourth storage class, allocated, for the storage returned by malloc and friends.
  • Kostas
    Kostas almost 6 years
    @paxdiablo If you were truly pedantic, you would refer to it as translation unit ;)
  • harper
    harper over 5 years
    @Palec Nope, your mentioned question has been posted years after this question.
  • Jens
    Jens almost 5 years
    Your (a) is redundant at best. No variable whatsoever is visible outside its scope. That's simply the definition of scope. What you mean is called linkage in the C Standard. static gives internal linkage to an identifier.
  • GermanNerd
    GermanNerd almost 5 years
    >Above program will give us this Output: First Counter Output = 1 Second Counter Output = 1 < Not true. Static variables get initialized only once. So the output will be 1, then 2, and so on.
  • GermanNerd
    GermanNerd almost 5 years
    @Jens 'register' is only a hint to the compiler; register storage cannot be enforced from within the C source. So I wouldn't consider it a storage class.
  • Jens
    Jens almost 5 years
    @GermanNerd I'm afraid the ISO C Standard disagrees with your view, as it clearly makes register a storage-class specifier (C99 6.7.1 Storage-class specifiers). And it is more than just a hint, for example you can't apply the address-of operator & on an object with storage class register regardless of whether the compiler allocates a register or not.
  • GermanNerd
    GermanNerd almost 5 years
    @Jens Thanks for reminding me about &. I might have done too much C++.....Anyhow, while 'register' is a storage-class specifier, in reality the compiler will likely create the same machine code for the (useless) 'auto' specifier as for the 'register' specifier. So the only thing remaining is the source-code level restriction of not being able to take an address. BTW, this little discussion led me to find a bug in Netbeans; since my latest update, it defaults to the g++ tool chain on new C projects!
  • RobertS supports Monica Cellio
    RobertS supports Monica Cellio almost 4 years
    IMHO the term "static global" is completely misplaced. A variable or function can't be local to a specific file and global (visible throughout the whole program) at the same time. We say "static global" because we mean a variable declared at global scope (outside of any function) inside a file, but technically it isn't real global. It is lets call it "regional" to keep the difference to "local" in the manner of function-local.
  • RobertS supports Monica Cellio
    RobertS supports Monica Cellio almost 4 years
    Because of this ambiguity there is much confusion brought to people who come newly to C. One good example is a recent question, where the OP used the term "static global" and confused him/herself as well as the answerers, here. You can get a short overview in the comments to that question.
  • RobertS supports Monica Cellio
    RobertS supports Monica Cellio almost 4 years
    @EliBendersky Since your answer is viewed by many new C programmers I would highly suggest you to replace the term "static global". It is ambiguous, formally incorrect and confuses people.
  • Jens
    Jens over 3 years
    The Wikipedia terminology is crap^Wwrong and should be removed. static does not "set scope" (scope is determined by the placement of a declaration inside or outside blocks). static sets the linkage of an identifier to internal linkage which means identifiers from other translation units cannot refer to it. This makes it possible to have a different object with the same name in another source file.
  • Jens
    Jens over 3 years
    Wikipedia at its worst. Static sets linkage, not scope. Understanding the difference is crucial.
  • Ekrem Dinçel
    Ekrem Dinçel over 3 years
    @YoushaAleayoub See this and this.
  • Sekomer
    Sekomer over 3 years
    In most C libraries all "private" functions are static and most "public" are not. Hello I have a question about this, you said most , I wonder how can static functions behave as public
  • Sekomer
    Sekomer over 3 years
    Global and Static variables are initialized to 0, You shouldn't re-assign them to zero in every function call.
  • Eljay
    Eljay over 3 years
    @Sekomer • if a static function pointer "escapes" as a function pointer return value of another function, or by being set as a function pointer via member variable in a struct.
  • natiiix
    natiiix over 3 years
    @Jens No one asking a question about static will know what linkage means. However, the concept of scope is common to practically all languages, so anyone should be able to roughly understand how static affects objects based on this description. For the same reason, it mentions "the containing file" rather than "the current compilation unit".
  • Jens
    Jens over 3 years
    @natiiix Linkage is not scope. static does not set scope. Even "the containing file" is wrong, since scope only starts at the end of a declarator, not at the beginning of a file. The Wikipedia entry as quoted is so misleading, it would make Trump blush.
  • natiiix
    natiiix over 3 years
    @Jens It doesn't really matter though, at all. For all intents and purposes, static makes global variables local to the file and removes them from the truly global scope. There's no point flexing fancy terms when a simple question expecting a simple, straight-forward answer is asked. Sure, it's not exactly correct, but it helps everyone understand the general idea and that's more important than some terminology nuances.
  • Nikolai Ehrhardt
    Nikolai Ehrhardt about 2 years
    Does it mean, I can not pass any char* to this function, because nobody knows if it could be incremented by 10 ... I doubt your answer, although its interesting.