开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜