a static variable in c

11,016

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.

Share:
11,016
Asher Saban
Author by

Asher Saban

Updated on June 04, 2022

Comments

  • Asher Saban
    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
    CB Bailey over 13 years
    How is static different for functions and variabls?
  • CB Bailey
    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
    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 replace source file with translation unit.
  • zneak
    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
    Prasoon Saurav over 13 years
    @Charles : Too quick! I was posting exactly the same thing. :D
  • aib
    aib over 13 years
    It'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
    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
    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
    CB Bailey over 13 years
    You 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
    aib over 13 years
    Ah, I see what you mean now. Fixed.
  • aib
    aib over 13 years
    Actually 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
    CB Bailey over 13 years
    It 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
    CB Bailey over 13 years
    I'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 them static is circular and doesn't really explain anything.
  • André Caron
    André Caron over 13 years
    +1 for posting a simple explaination and solution instead of going through lots of accurate, but gory details.
  • aib
    aib over 13 years
    How did I know you'd say that? :) Removed all references to the other usage.