开发者

Static variables in C and C++

开发者 https://www.devze.com 2022-12-24 16:06 出处:网络
Is there any difference between a vari开发者_Go百科able 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

Is there any difference between a vari开发者_Go百科able 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?


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')


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.


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.


I want to add to Southern Hospitality's answer Static variables in C and C++

the following remarks:

The use of static to indicate "local to translation unit" is deprecated in C++ ( href="https://rads.stackoverflow.com/amzn/click/com/0201700735" rel="nofollow noreferrer" 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.)


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.

0

精彩评论

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

关注公众号