2

I wrote in

// In file t.h

#ifndef __t_h__
#define __t_h__
static int abc;
#endif

--

//In   main.c
    #include <stdio.h>
    #include "t.h"
    int main()
    {
        abc++;printf("%d \n", abc);
        test();
    }

- -

//In test.c

#include <stdio.h>
#include "t.h"

void test()
{
    abc++;
    printf("%d \n", abc);
}

When I run the project I found the output of abc is 1 and 1. But when I change it to int abc in t.h. The output of abc = 1 and 2. Why static is not retaining the value when the control reaches to test.c file. If it won't retain then why should not it provide an error as the static variable can not be shared between/among the files?

Nandkumar Tekale
  • 16,024
  • 8
  • 58
  • 85
Rasmi Ranjan Nayak
  • 11,510
  • 29
  • 82
  • 122
  • 3
    I would suggest you read more about the basics of C, especially concentrating on variables and lifetime/visibility/linkage of variables, and what the `static` keyword actually means. – Some programmer dude Jun 27 '12 at 05:49

4 Answers4

9

static variables has internal linkage which means each translation unit gets its own copy.

So in your program each .cpp file which includes t.h has its own copy of the static variable, which in turn means, there are two objects in the memory. You can try printing their addresses to confirm this, as they will be different.

That makes the situation pretty simple: if you change the object in one .cpp, it doesn't reflect in the other .cpp file, because the object in the other .cpp file is a different object. Why should it change?

But when you change it to int abc (i.e don't make it static), then each translation unit has same object. If you change it in one file, it will be reflected in other file also, as expected.


As for sharing, then yes, static objects can be shared between two functions in the same translation unit, but they cannot be shared between two translation units.

Search for translation unit on this site, you will get many topics on it. Read them, then you will understand it fully.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • Is not this a sharing of variable? According to http://stackoverflow.com/questions/1045501/how-do-i-share-variables-between-different-c-files – Rasmi Ranjan Nayak Jun 27 '12 at 05:57
  • @RasmiRanjanNayak: What do you mean by "sharing of variable"? Sharing between *what*? Static objects can be shared between two functions in the same translation unit, but they cannot be shared between two translation units. – Nawaz Jun 27 '12 at 05:58
  • @Rasmi - There is a **huge** difference between `extern int` and `static int`. One is shared, one is not. – Bo Persson Jun 27 '12 at 07:49
  • @BoPersson: Could you please elaborate little more? – Rasmi Ranjan Nayak Jun 27 '12 at 07:55
  • @RasmiRanjanNayak: `static int a` declares a variable which has internal linkage, while `extern int a` declares a variable which has external linkage. Search for these term terms (*internal* and *external* linkage) on this forum, you get hundreds of topics. – Nawaz Jun 27 '12 at 15:40
  • @RasmiRanjanNayak: Here you go : [What is external linkage and internal linkage in C++](http://stackoverflow.com/questions/1358400/what-is-external-linkage-and-internal-linkage-in-c) ... and [What are extern variables in C?](http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c) – Nawaz Jun 27 '12 at 15:43
4

When you declare a static variable in header file a copy of the static variable is created in each Translation unit where the header is included. So each of the translation units involved in your program has its own copy of abc now and hence you get the observed behavior.The behavior is not what you expected but it well defined one.

static variable can not be shared between/among the files?

No they cannot be! that is the very purpose of making them static

static variables have internal linkage. Their scope is restricted to the the translation unit in which they are declared. They cannot be accessed beyond the TU.If you want to share the same variable across different Translation units You should drop the static and use extern, which gives the variable an external linkage and hence visibility across different translation units.

Good Read:
How do I use extern to share variables between source files?

Community
  • 1
  • 1
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • You can't have access to an external static variable; their symbols are not exported at link time. – lvella Jun 27 '12 at 05:53
  • @lvella: There is nothing called as external static variables.There can be either extern variables or static not both. – Alok Save Jun 27 '12 at 05:58
  • There may not be possible to declare/use an external static variable for the reason I stated (they are not accessible, thus the language specs were made to forbid it), but conceptually there is nothing wrong with the statement. Such variables are static variables in a module different from the one you are referring to/working in. – lvella Jun 27 '12 at 16:27
  • @lvella: I don't see the point.`static` has internal linkage, `extern` has external linkage,So clearly it doesn't make any sense that one could have a `static extern` variable.And the language specs forbid it for the same reason. – Alok Save Jun 27 '12 at 19:13
4

When the preprocessor is done with your code, main.c looks like

// omitted stuff from stdio
static int abc;
int main()
{
    abc++;printf("%d \n", abc);
    test();
}

and test.c looks like

// omitted stuff from stdio
static int abc;
void test()
{
    abc++;
    printf("%d \n", abc);
}

So each file contains its own variable abc that is not accessible from the other.

One solution would be to change t.h to

#ifndef __t_h__
#define __t_h__
extern int abc;
#endif

and then change main.c to

#include <stdio.h>
#include "t.h"
int abc;
int main()
{
    abc++;printf("%d \n", abc);
    test();
}

You can think about it like this: there's now only one int abc in your program, in main.c but test.c knows about its existence because the extern int abc tells test.c that somewhere else in the project there is an integer called abc that it will be able to find at link time.

Wernsey
  • 5,411
  • 22
  • 38
1

In C, static has two usages:

1, Use static keyword to limit the var's scope in the translation unit. To make this simple, if you have two files: a.c, b.c and you wrote:

static int varA;

in a.c, then this means varA could only be used in a.c, if you want to use varA in b.c, you should remove the static keyword, and add extern int varA; in b.c, what people usually do is we create another file called: a.h, and write extern int varA; in a.h, and we simply include "a.h" in b.c, so we could write every variable we want to extern in a.h and use a single include "a.h" to make these variables or functions legal in other .c files(i.e. source files)

2, Using static to define a local variable in a function, for instance:

int TheFunction()
{
  static int var = 0;
  return ++var;
}

Because you used the static keyword on a local variable var, this variable will not loss when TheFunction() is returned.

The first time you call TheFunction() you will get 1, the second time you call TheFunction() you will get 2, and so on.

Next, lets see the usage of static in C++.

Because any C++ complier can complie a C code, so the 2 usages above is also in C++.

another two usages is: 1, static member variable. 2, static member function.

Lets see the code directly:

#include <iostream>

using namespace std;


class Test
{
public:
    Test() : m_nNormalVar(0)
    {

    }
public:
    // You need to init this static var outside the class
    // using the scope operator:
    // int Test::m_nStaticVar = 0;
    static int m_nStaticVar;

    // You can init this const static var in the class.
    const static int m_nConstStaticVar = 10;

    // This is just a normal member var
    int m_nNormalVar;
};
int Test::m_nStaticVar = 0;

int main(int argc, char *argv[])
{
    Test a;
    Test b;
    a.m_nStaticVar++;
    a.m_nNormalVar++;
    cout << b.m_nStaticVar << endl;
    cout << b.m_nNormalVar << endl;

    return 0;
}

a and b are objects of class Test they have the same m_nStaticVar and the same m_nConstStaticVar, but they have their own m_nNormalVar this is a static member variable.

#include <iostream>

using namespace std;


class Utility
{
public:
    // This is a static member function, you don't
    // need to have a concrete object of this class
    // to call this function.
    static int SelectMax(int a, int b)
    {
        return a > b ? a : b;
    }
};

int main(int argc, char *argv[])
{
    // No objects of class Utility
    cout << Utility::SelectMax(2, 1) << endl;

    return 0;
}

So this is a static member function of a class in C++.

These four ways of static's usage is all I known, if there are still some other usages, please help to edit this post, thx:)

EDIT:

Add static global function

1, Use static keyword to limit the function's scope in the translation unit. To make this simple, if you have two files: a.c, b.c and you wrote:

static void StaticFunction();

in a.c, so you can only call StaticFunction() in a.c, if you want to call this function in b.c you should remove the static keyword and then delcare it before the usage. Or just declare it in a.h and include "a.h" in b.c

shengy
  • 9,461
  • 4
  • 37
  • 61
  • -1: "will be allocated on the Global Stack" - sorry there is no global stack. This is static variable by it s nature. Plus stack. How can you call this stack??? – Kirill Kobelev Jun 27 '12 at 06:18
  • @KirillKobelev removed the Global Stack part – shengy Jun 27 '12 at 06:48
  • If you distinguish between static member fields and static member functions, you should also talk about static global functions (and not just static global variables) – danielschemmel Jun 27 '12 at 07:19