Can a variable be declared both static and extern?
This is specifically given as an example in the C++ standard when it's discussing the intricacies of declaring external or internal linkage. It's in section 7.1.1.7, which has this exert:
static int b ; // b has internal linkage
extern int b ; // b still has internal linkage
extern int d ; // d has external linkage
static int d ; // error: inconsistent linkage
Section 3.5.6 discusses how extern
should behave in this case.
What's happening is this: static int i
(in this case) is a definition, where the static
indicates that i
has internal linkage. When extern
occurs after the static
the compiler sees that the symbol already exists and accepts that it already has internal linkage and carries on. Which is why your second example compiles.
The extern
on the other hand is a declaration, it implicitly states that the symbol has external linkage but doesn't actually create anything. Since there's no i
in your first example the compiler registers i
as having external linkage but when it gets to your static
it finds the incompatible statement that it has internal linkage and gives an error.
In other words it's because declarations are 'softer' than definitions. For example, you could declare the same thing multiple times without error, but you can only define it once.
Whether this is the same in C, I do not know (but netcoder's answer below informs us that the C standard contains the same requirement).
static variable followed by extern in the same file
You can declare a variable static
then extern
, but not extern
then static
. The result is that the global a
still has internal linkage. There is a very similar example (using b
as the variable name) in the language standard doc, section [dcl.stc]
, that states this.
Why won't extern link to a static variable?
The whole and entire purpose of static
is to declare that a variable is private to the source file that it is declared in. Thus, it is doing precisely its job in preventing a connection from an extern.
Keep in mind that there are four flavors of file-scope variable definition:
int blah = 0;
— blah is defined in this file and accessible from other files. Definitions in other files are duplicates and will lead to errors.extern int blah;
— blah must be defined elsewhere and is referenced from this file.int blah;
— This is the moral equivalent of FORTRANCOMMON
. You can have any number of these in files, and they are all resolved by the linker to one sharedint
. (*)static int blah;
(optionally with an initializer) — This is static. It is completely private to this file. It is not visible to externs in other files, and you can have many different files that all declarestatic TYPE blah;
, and they are all different.
For the purists in the audience: 'file' = compilation unit.
Note that static inside functions (not at file scope) are even more tightly scoped: if two functions declare static int bleh = 0;
even in the same file, they are unrelated.
(*): for those of you not familiar: in the usual pattern, one compilation unit has to define a global variable, and others can reference it. It 'lives' in that compilation unit. In case (3), above, no file (or all the files) defines it. If two files say int blah = 0;
, the linker will complain of multiple definitions. If two files say int blah;
the linker cheerfully creates a single global int
and causes all the code to refer to it.
What is the difference between static and extern in C?
From http://wiki.answers.com/Q/What_is_the_difference_between_static_and_extern:
The static storage class is used to declare an identifier that is a local variable either to a function or a file and that exists and retains its value after control passes from where it was declared. This storage class has a duration that is permanent. A variable declared of this class retains its value from one call of the function to the next. The scope is local. A variable is known only by the function it is declared within or if declared globally in a file, it is known or seen only by the functions within that file. This storage class guarantees that declaration of the variable also initializes the variable to zero or all bits off.
The extern storage class is used to declare a global variable that will be known to the functions in a file and capable of being known to all functions in a program. This storage class has a duration that is permanent. Any variable of this class retains its value until changed by another assignment. The scope is global. A variable can be known or seen by all functions within a program.
Whether Global Variables in C, static or extern?
Global Variable in C by default corresponds to
static
storage class but has external linkage. Does this mean it is partiallystatic
and partiallyextern
?
The English word “static” has muddled and multiple meanings in C, and, yes, the default for a variable declared outside a function is to have static storage duration and external linkage.
Because there are multiple concepts here and some mixed use of word meanings, we should clarify some terminology and formatting:
- Use code style to refer to specific text in source code, such as the keyword
static
. When speaking of static storage duration or external linkage, “static” and “external” are mere English adjectives and should not be in code style. - “Global” means visible throughout an entire program. The C standard does not use this word for this purpose. It uses “external” to refer to things that are outside of (external to) any function. (But it also uses “external” for other purposes.) A global variable could not have internal linkage, because it would not be visible throughout the entire program.
- A variable consists of an object (memory reserved for representing the value) and an identifier (the name). Storage duration is a property of the object. Linkage is a property of the identifier.
The English word “static” generally means unchanging. The C standard uses this word and the keyword static
in multiple ways:
- Static storage duration means the memory for an object is reserved throughout all of program execution.
- Using the
static
keyword in a declaration, other than as below, both gives an object static storage duration and, in a declaration outside a function, gives the identifier internal linkage. - Using the
static
keyword inside subscript markers in a parameter declaration, as invoid foo(int a[static 3])
, indicates that the parameter points to at least the stated number of elements. - Static assertions, using
_Static_assert
, provide compile-time tests (which can help detect bugs or ensure a program is being compiled with expected settings).
These multiple uses are unfortunate and are due at least partly to the history of how the C language was developed.
static and extern global variables in C and C++
Global variables are not extern
nor static
by default on C and C++.
When you declare a variable as static
, you are restricting it to the current source file. If you declare it as extern
, you are saying that the variable exists, but are defined somewhere else, and if you don't have it defined elsewhere (without the extern
keyword) you will get a link error (symbol not found).
Your code will break when you have more source files including that header, on link time you will have multiple references to varGlobal
. If you declare it as static
, then it will work with multiple sources (I mean, it will compile and link), but each source will have its own varGlobal
.
What you can do in C++, that you can't in C, is to declare the variable as const
on the header, like this:
const int varGlobal = 7;
And include in multiple sources, without breaking things at link time. The idea is to replace the old C style #define
for constants.
If you need a global variable visible on multiple sources and not const
, declare it as extern
on the header, and then define it, this time without the extern keyword, on a source file:
Header included by multiple files:
extern int varGlobal;
In one of your source files:
int varGlobal = 7;
Are static class variables the same as extern variables, only with class scope?
Yes, both have static storage duration and external linkage; they have essentially the same run-time properties, only differing in (compile-time) visiblity.
Related Topics
Ways to Detect Whether a C++ Virtual Function Has Been Redefined in a Derived Class
Segmentation Fault with Char Array and Pointer in C on Linux
How to Use C++14 Features When Building Qmake Projects
C++11 Std::Mutex in Visual Studio 2012 Deadlock When Locked from Dllmain()
Pass Arrays from C/C++ to Fortran and Return a Calculated Array
Deleted Function in Std::Pair When Using a Unique_Ptr Inside a Map
Why Is My Double or Int Value Is Always 0 After Division
Using an Iterator to Divide an Array into Parts with Unequal Size
What Does -Fpic Mean When Building a Shared Library
Narrowing Conversion from Unsigned to Double
Incomplete Class Usage in Template
Why Does a Virtual Function Get Hidden
Qdialog Exec() and Getting Result Value
Removing '#Include <Algorithm>' Doesn't Break the Code
How to Use Unicode Range in C++ Regex
C++:Handle Resources If Constructors May Throw Exceptions (Reference to Faq 17.4]