a static variable in c
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!
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.
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!
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.
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.
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
.
It's because the static variable is declared in the header. In C, static variables exist only in the .c file in which they're declared. Since your .h is included (#include
directives can be seen as nothing more than a copy-paste operation) in two distinct .c files, two static variables named counter
are created, one in each file. Your test file increments its local counter
variable, but the one returned by getUsersNum
is from another C file and is completely independent.
What the question tries to do is access a static variable from a file other than the one in which it was declared. You should know that it's not (directly) possible. To increment the right counter, you will need a function that operates on Counter.c's counter
variable.
A static
variable is only accessible in the file in which it's defined. In this example, Counter.c
and CounterMain.c
both have their own counter
variable.
When ++counter
is executed, this updates the variable declared in CounterMain.c
. But when getUsersNum()
is called, this returns the value of the counter
variable from Counter.c
, which hasn't been incremented.
If you change getUsersNum()
to counter
, you'll see the counter
variable declared in CounterMain.c
has been incremented.
精彩评论