a static variable in c
Solution 1
Just think of it as ".h files don't exist". What happens is that the .h files are included inside the .c files and only the .c files get compiled (and linked (mixed) together).
In your case you have 2 .c files with
static int counter = 0;
Each counter
is specific to the .c file it is in. The counter
in CounterMain.c is a different variable than the counter
in Counter.c.
You need to have one single definition of counter. You can have several declarations (typically in .h files)
/* .h file */
extern int counter;
/* .c file(s) that use the counter but don't define it */
#include "file.h"
/* .c file that **defines** counter */
#include "file.h"
int counter = 0;
Ohhhhhhhhhhhhhhhhhh and there's the static
thing. Don't use it at global scope!
Solution 2
In C, the scope of a static variable is the source file in which its defined.
Since you're loading this header into 2 separate .c files, each file gets a unique variable. Incrementing "counter" in one file does not affect the "static" variable in the other file.
For details, see this description. In order for the variable to be visible and shared in multiple files, it needs to be declared as extern. Otherwise:
Static global variables: variables declared as static at the top level of a source file (outside any function definitions) are visible throughout that file ("file scope").
Which is the case here.
Solution 3
A C program is made by combining one or more translation units together to make a program.
A translation unit is, in effect, a preprocessed source file. It contains any included header and source files specified in #include
directives, and excludes anything excluded by #if
or similar directives.
When a variable at file scope is declared static
it gives the variable name internal linkage. This means that the name refers to an object local to the translation unit in which it appears. If the name is used in another translation unit then it cannot refer to the object in this translation unit, it must refer to a different object.
[In contrast, a name with external linkage refers to the same object whatever translation unit the name is used in.]
static int counter = 0;
When you put a declaration such as this in a header file, it means that every translation unit that includes the header file has its own unique object called counter
that is distinct from any object called counter
in any other translation unit.
In your case there is one counter
in the translation unit generated from CounterMain.c
and a separate one in the translation unit generate from Count.c
. The one in Count.c
is never incremented but is returned by getUserNum()
, the one in CounterMain.c
is incremented in main
but never used anywhere else.
Solution 4
static int counter = 0;
If a variable has been defined using the static storage class specifier the variable has an internal linkage. That means you can use counter
inside the same translation unit in which it is defined.
Solution 5
The static
keyword means, when used to qualify functions or global variables, that the function or variable should have internal linkage
, meaning it shouldn't be visible as a global symbol. Therefore, each compilation unit including Counter.h
will have its own local copy of counter
which won't clash with others.
In this case, Counter.c
and CounterMain.c
have different variables count
, resulting in what you have described.
The solution is to change the definition of counter
in Counter.h
to a declaration:
extern int counter;
and to put the definition in Counter.c
:
int counter = 0;
Afterwards CounterMain
and any other compilation units including Counter.h
should be able to access the single instance counter
, but you may want to indulge in information hiding
and only access it through functions in Counter
, resulting in a cleaner interface
.
Asher Saban
Updated on June 04, 2022Comments
-
Asher Saban almost 2 years
Hi I'm studying for my test in C and i've encountered a question which i can't figure its answer.
A programmer wrote a program to count number of users (Count.h, Count.c):
/******** FILE: Counter.h ***********/ static int counter = 0; int getUsersNum (); /******** END OF FILE: Counter.h ****/ /******** FILE: Counter.c ***********/ #include "Counter.h" int getUsersNum () { return counter; } /******** END OF FILE: Counter.c ****/
And a tester to test it:
/******** FILE: CounterMain.c ***********/ #include "Counter.h" #include <stdio.h> int main () { int i; for (i=0;i<5;++i) { ++counter; printf ("Users num: %d\n", getUsersNum()); } return 0; } /******** END OF FILE: CounterMain.c ****/
Suprisingly the output was:
Users num: 0 Users num: 0 Users num: 0 Users num: 0 Users num: 0
I can't see why with this use of static variable the counter does not advance.. why did they get such input?
thank you all!
-
CB Bailey over 13 yearsHow is
static
different for functions and variabls? -
CB Bailey over 13 years"Source file" is confusing because a header file is a source file and the variable is only declared in one source file. Translation unit would be more accurate.
-
Prasoon Saurav over 13 years
In C, the scope of a static variable is the source file in which its defined
. You might want to replacesource file
withtranslation unit
. -
zneak over 13 years@Charles Bailey It's different once you delve down into the generated code, but if you look only at the C level, it's semantically pretty much the same.
-
Prasoon Saurav over 13 years@Charles : Too quick! I was posting exactly the same thing. :D
-
aib over 13 yearsIt's not for functions and global variables: It changes the linkage as I've explained (I've edited my answer to read "variable or function"). With simple local variables, it means "static storage and lifetime", i.e. a plain old static variable.
-
Reed Copsey over 13 years@Prasoon and @Charles: That was a direct quotation, not my text. That was why I specifically mentioned ".c files" in my answer..
-
Reed Copsey over 13 years@Prasoon: While "translation unit" is correct, it's not going to be as obvious to the original poster...
-
CB Bailey over 13 yearsYou mean it has a different meaning when applied to objects with block scope as opposed to when applied to functions and objects with file scope. Your first sentence is ambiguous as you don't say what context you are comparing against when saying "has a different meaning".
-
aib over 13 yearsAh, I see what you mean now. Fixed.
-
aib over 13 yearsActually I was planning on just linking to another question which explained the different usages of
static
, but just couldn't find a good one. -
CB Bailey over 13 yearsIt may not be obvious and it may need explaining but I think that it's necessary to use the concept of a translation unit to explain the behaviour whether or not you use the correct technical term. Using the term "source file" loosely is likely to be more confusing IMHO.
-
CB Bailey over 13 yearsI'm going to sound pedantic now and it's not important because it's not central to the original question but saying that
static
applied to local variables makes themstatic
is circular and doesn't really explain anything. -
André Caron over 13 years+1 for posting a simple explaination and solution instead of going through lots of accurate, but gory details.
-
aib over 13 yearsHow did I know you'd say that? :) Removed all references to the other usage.