Static VS Extern "C"/"C++"

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.

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;

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 partially static and partially extern?

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 in void 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 vs extern C/C++

Yes, you are just lucky :) The extern "C" is one language linkage for the C language that every C++ compiler has to support, beside extern "C++" which is the default. Compilers may supports other language linkages. GCC for example supports extern "Java" which allows interfacing with java code (though that's quite cumbersome).

extern "C" tells the compiler that your function is callable by C code. That can, but not must, include the appropriate calling convention and the appropriate C language name mangling (sometimes called "decoration") among other things depending on the implementation. If you have a static member function, the calling convention for it is the one of your C++ compiler. Often they are the same as for the C compiler of that platform - so i said you are just lucky. If you have a C API and you pass a function pointer, better always put one to a function declared with extern "C" like

extern "C" void foo() { ... }

Even though the function pointer type does not contain the linkage specification but rather looks like

void(*)(void)

The linkage is an integral part of the type - you just can't express it directly without a typedef:

extern "C" typedef void(*extern_c_funptr_t)();

The Comeau C++ compiler, in strict mode, will emit an error for example if you try to assign the address of the extern "C" function of above to a (void(*)()), beause this is a pointer to a function with C++ linkage.

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:

  1. 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.
  2. extern int blah; — blah must be defined elsewhere and is referenced from this file.
  3. int blah; — This is the moral equivalent of FORTRAN COMMON. You can have any number of these in files, and they are all resolved by the linker to one shared int. (*)
  4. 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 declare static 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.

Extern for Global and static global variables

Could anyone please explain how is it possible to use extern for
static global variable in c++?

No, it is not possible. For more details, please continue reading.

You can not use static global in other file even if you use extern (If I rephrase extern and static are conflicting specifiers)

But life time of static global is throughout the life of program.

The only way to use static in different compilation unit (source file) is to pass the address of this static variable to other file and use it by dereferencing the pointer.

If i have a header file with both global and static global variables
and i include it in my source file ans use extern for both and print
values its printing

static global This works because difference instances of variable is created for each source file. So if you change the value of variable in one of the file, it won't be reflected in other source file because physical location of both files are different.

non-static global extern int global is a declaration which goes into each source file via header file. All of them are lodged at physically same location. So if you change its value in one of the file, it would be reflected in other files also.


Further readings: storage duration

Internal linkage. The name can be referred to from all scopes in the
current translation unit.
Any of the following names declared at
namespace scope have internal linkage variables, functions, or
function templates declared static

And

external linkage. The name can be referred to from the scopes in the other translation units. Variables and functions with external
linkage also have language linkage, which makes it possible to link
translation units written in different programming languages.

variables and functions not listed above (that is, functions not
declared static, namespace-scope non-const variables not declared
static, and any variables declared extern)



Related Topics



Leave a reply



Submit