views:

990

answers:

5

Is there any difference between a variable declared as static outside any function between C and C++. I read that static means file scope and the variables will not be accessible outside the file. I also read that in C, global variables are static . So does that mean that global variables in C can not be accessed in another file?

+4  A: 

No, there's no difference between C and C++ in this respect.

Read this SO answer about what static means in a C program. In C++ there are a couple of other meanings related to the use of static for class variables (instead of instance variables).

Regarding global vars being static - only from the point of view of memory allocation (they are allocated on the data segment, as all globals are). From the point of view of visibility:

static int var;    // can't be seen from outside files
int var;           // can be seen from outside files (no 'static')
Eli Bendersky
so how do I access a variable outside the file in C ? `extern` will not work with `static` right? may be I am too confused..
Naveen
@Naveen: there's no problem, *unless* you've declared it `static`
Eli Bendersky
Ok..so in the second case, what will be the storage class for the variable `var`? is there any name for it or is it simply called global variable?
Naveen
@Naveen: it's a global variable
Eli Bendersky
@Naveen: It has static storage. Keep in mind static storage and the static keyword aren't mutual. Any variable that isn't dynamic (created from the heap) or automatic (must be created in a local scope) is static. While the static keyword gives something static storage, it does more. (Makes it invisible outside the translation unit.) Contrarily, you can still have something with static storage be visible outside the unit, by omitting the specifer.
GMan
@GMan: Thanks, much clearer now. T
Naveen
+4  A: 

There are two concepts here "static linkage (or scope)" and static allocation".

Outside a function the keyword refers to linkage, inside it refers to allocation. All variables outside a function have static allocation implicitly. An unfortunate design perhaps, but there it is.

Clifford
+2  A: 

C and C++ are the same.

static does two different things.

For variables declared outside a function scope, it changes the visibility (linkage) of the variable. The variable will be a global variable since it is outside a function scope. If it isn't static, it will have universal linkage (visibility) so any code linked together with this can access it (they may have to declare it extern). If the variable is outside a function scope and is static, it still a global variable in that it always exists and keeps its value, but no code outside the same compilation unit (that .c file and any .h's included) can access it.

For variables declared inside a function scope, static changes the location where the variable is stored. If it is not static, it will be an automatic variable, that means it disappears as the function exits and comes back into existence (on the stack) when the function is entered again. This it loses its value when you exit the function. And also any references to it (pointers to it) are invalid after the function exits. If a variable declared inside a function scope is static, then it makes it not an automatic variable but a globally allocated one. So the variable will exist after the function exits and thus will keep its value across invocations of the function and also any references (pointers) to it are valid even after the function exits. Note that in both cases the scope of the variable is only within that function so it's not possible to access it directly (but only via saved reference) from outside the function scope.

One last thing static does is change when the initializer (i.e. int foo = 5) for the variable is run. For all the cases where the allocation is global (every case except the automatic one), the initializer is run only once, at the beginning of the execution of your program. It is run before main() is run even, so you can get some not quite expected result if your initializer isn't just a constant number but runs some code. For the automatic case, the initializer is run every time the function is entered, and in this case it is always after main() has been entered.

Southern Hospitality
Are you sure that static variables inside a function get initialized before main()? I always thought they were initialized the first time the function was called, and that's also what the answers here say: http://stackoverflow.com/questions/246564/what-is-the-lifetime-of-a-static-variable-in-a-c-function
Ben Voigt
The answers in that thread are for C++. I guess my assumption that C and C++ do it the same is incorrect. Some looking says that C only allows constant initializers and they are filled at compile time, not runtime. So that is before main() to my credit. But I was wrong about the rest, C++ does it differently and so all the cases that matter should be interpreted according to the link you inserted.
Southern Hospitality
A: 

I want to add to Southern Hospitality's answer http://stackoverflow.com/questions/2528457/static-variables-in-c-and-c/2528624#2528624

the following remarks:

The use of static to indicate "local to translation unit" is deprecated in C++ ( href="http://rads.stackoverflow.com/amzn/click/0201700735" The C++ Programming Language: Special Edition, Appendix B.2.3, Deprecated Features).

You should use unnamed namespaces instead:

static int reply = 42; // deprecated

namespace {
    int reply1 = 42;  // The C++ way
}

As already said by Southern Hospitality, the order of initialization of global objects is undefined. In that situation, you should consider using the href="http://en.wikipedia.org/wiki/Singleton_pattern#C.2B.2B", Singleton pattern.

UPDATE: GMan commented my answer:

"The order is defined per-translation unit, ...": This really slipped my mind, so I looked it up in The C++ Programming Language.

In Section 9.4.1, Initialization of Non-local Variables, Prof. Stroustrup suggests that "a function returning a reference is a good alternative to a global variable":

int& use_count()
{
        static int uc = 0;
        return uc;
}

"A call to use_count() now acts as a global variable that is initialized at its first use. For example:"

void f()
{
        std::cout << ++use_count() << '\n';
}

In my understanding, this is very similar to the Singleton pattern.

GMan commented further: "We need to limit our ability to create these objects to one, and provide global access to it." Does the limiting to one really relate to anything in the problem? We may need one globally, but who's to say we don't want it in other places?"

Some quotes from Singleton(127) (Gamma et al, Design Patterns):

"The Singleton pattern is an improvement over global variables. It avoids polluting the name space with global variables that store sole instances."

"The pattern makes it easy to change your mind and allow more than one instance of the Singleton class."

Singletons are initialized in the order they are first used.

In Herb Sutter, Andrei Alexandrescu, C++ Coding Standards, Item 10 says:

"Avoid shared data, especially global data."

Therefore I use often Singletons to avoid global data. But of course, as everything is overusable, this could be a overuse of the Singleton pattern. (Johshua Kerievsky calls this "Singletonitis" in his book "Refactoring to Patterns".)

UPDATE 2:

(Sorry, but I cannot write comments, therefore this Update.)

Jalf wrote in his comment: "The gang of four were smoking something illegal when they wrote about the singleton pattern."

Obviously, other C++ developers smoked interesting substances, too. For example, Herb Sutter (he served for over a decade as secretary and chair of the ISO C++ standards committee during the development of the second C++ standard, C++0x, and as lead architect of C++/CLI at Microsoft. Herb is currently the designer of the Prism memory model for Microsoft platforms and the Concur extensions to Visual C++ for parallel programming), wrote in C++ Coding Standards, Item 21:

"When you need such a (namespace level) variable that might depend upon another, consider the Singleton design pattern; used carefully, it might avoid implicit dependencies by ensuring that an object is initialized upon first access. Still, Singleton is a global variable in sheep's clothing, and is broken by mutual or cyclic dependencies."

So, avoid global data, if you can. But if you have to use global data in separate translation units, Singleton should be an acceptable solution for enforcing a specific initialization sequence.

Note that in the Java language global data does not even exist. Obviously, global data is substituted/emulated by the use of the Singleton design pattern.

(For I am working in my dayjob with a Java team, I strive for a maximal similarity of my C++ programs with Java programs. E.g, every class is situated in its own source file/translation unit.)

gh57.at
The order is defined per-translation unit, for what it's worth. But I hope you see the singleton pattern isn't the solution. "Initialization order across units is unspecified" -> "We need to limit our ability to create these objects to one, and provide global access to it." Does the limiting to one really relate to anything in the problem? We may need one *globally*, but who's to say we don't want it in other places?
GMan
@edit: Singletons are global data, no matter how you dress it up. May as well take out the unnecessary restrictions and create a global wrapper. http://jalf.dk/blog/2010/03/singletons-solving-problems-you-didnt-know-you-never-had-since-1995/
GMan
How does your quote from Gamma et al even make sense?Global instances no more pollute a namespace than singletons do. (take `std::cout` as an example. One global instance, visible in the std namespace. How is your `f` function better? That to is visible in the namespace it's declared in. As for the second part, no, singletons make it **much much harder* to change your mind. Your entire codebase is littered with getInstance() calls or implicit accesses of static data. I stand by my conclusion: The gang of four were smoking something illegal when they wrote about the singleton pattern.
jalf
A: 

Not really a direct answer to your question, but something closely related to watch out for if you use both C and C++.

In C++, unlike C, global variables which are declared "const" are implicitly local to the translation unit, AS IF "static" had been used.

Example:

// file A
extern const int glob;

// file B
const int glob = 42;

This will work if you are using a C compiler but not with a C++ compiler. In C++, the glob variable in file B cannot be used from file A and the linker will generate an "unresolved reference" error.

Ben Voigt