Simultaneously creating internal and external linkages in C - c

I was reading a C reference about linkage (external, internal and none) and came across the following:
If, within a translation unit, the same identifier appears with both
internal and external linkage, the behavior is undefined.
I wanted to know how this undefined behavior can occur. Based on what I had read, a variable can have only one storage class. So it cannot be declared both static and extern at the same time.
So in what scenario can a variable have both internal and external linkage?

In this code:
extern int x;
static int x;
The first declaration says x has external linkage, and the second declaration says it has internal linkage.

Related

Can a variable be both static and extern [duplicate]

Why the following doesn't compile?
...
extern int i;
static int i;
...
but if you reverse the order, it compiles fine.
...
static int i;
extern int i;
...
What is going on here?
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).
For C, quoting the standard, in C11 6.2.2: Linkage of identifiers:
3) If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.
4) For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible, if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the
linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.
(emphasis-mine)
That explains the second example (i will have internal linkage). As for the first one, I'm pretty sure it's undefined behavior:
7) If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.
...because extern appears before the identifier is declared with internal linkage, 6.2.2/4 does not apply. As such, i has both internal and external linkage, so it's UB.
If the compiler issues a diagnostic, well lucky you I guess. It could compile both without errors and still be compliant to the standard.
C++:
7.1.1 Storage class specifiers [dcl.stc]
7) A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has
internal linkage because of a previous declaration and provided it is not declared const. Objects declared
const and not explicitly declared extern have internal linkage.
So, the first one attempts to first gives i external linkage, and internal afterwards.
The second one gives it internal linkage first, and the second line doesn't attempt to give it external linkage because it was previously declared as internal.
8) The linkages implied by successive declarations for a given entity shall agree. That is, within a given scope,
each declaration declaring the same variable name or the same overloading of a function name shall imply
the same linkage. Each function in a given set of overloaded functions can have a different linkage, however.
[ Example:
[...]
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
[...]
In Microsoft Visual Studio, both versions compile just fine.
On Gnu C++ you get an error.
I'm not sure which compiler is "correct". Either way, having both lines doesn't make much sense.
extern int i means that the integer i is defined in some other module (object file or library). This is a declaration. The compiler will not allocate storage the i in this object, but it will recognize the variable when you are using it somewhere else in the program.
int i tells the compiler to allocate storage for i. This is a definition. If other C++ (or C) files have int i, the linker will complain, that int i is defined twice.
static int i is similar to the above, with the extra functionality that i is local. It cannot be accessed from other module, even if they declare extern int i. People are using the keyword static (in this context) to keep i localize.
Hence having i both declared as being defined somewhere else, AND defined as static within the module seems like an error. Visual Studio is silent about it, and g++ is silent only in a specific order, but either way you just shouldn't have both lines in the same source code.

Does this invoke undefined behavior with linkage in C?

From section (6.2.2/7) C99 Standard
7. If, within a translation unit, the same identifier appears with
both internal and external linkage, the behavior is undefined.
While the following generates a compile time error due to conflict of definitions
// 'x' has external linkage
extern int x;
// Here, 'x' has internal linkage
static int x;
But the following compiles fine,
// 'x' has external linkage
extern int x;
void foo() {
// Here, 'x' has internal linkage
static int x;
}
Do both the cases invoke an undefined behavior?
Your question stems from an incorrect assumption that a locally declared static variable has internal linkage. In reality a static variable declared in a block scope has no linkage. See 6.2.2/6
6 The following identifiers have no linkage: an identifier declared to
be anything other than an object or a function; an identifier declared
to be a function parameter; a block scope identifier for an object
declared without the storage-class specifier extern.
Only file-scope declaration can have external or internal linkage (plus local extern declarations).
Therefore 6.2.2/7 and your question simply do not apply.
As far as I know, it doesn't, since the two variables aren't the same. The local variable takes priority over the global one, and in the scope of foo(), it's declared only once. See the assembler output - the compiler will most likely translate the two variables into two different symbols.

Unable to use extern and static storage-class specifiers together

In C99 6.7.1 it says
At most, one storage-class specifier may be given in the declaration
specifiers in a declaration
I know extern and static are both storage class specifiers but extern basically states to the compiler that the variable is declared elsewhere and worry about it later. extern and static to me are NOT mutually exclusive. It is very well possible that something could be extern and static.
Why can't we use extern and static together? Is there a good reason other than the standard simply says, no?
Well, static means Internal Linkage, extern means External Linkage.
Internal Linkage refers to everything only in scope of a Translation unit.
External Linkage refers to things that exist beyond a particular translation unit. In other words, accessable through the whole program.
So both are mutually exclusive.
"Static" outside all blocks means "internal linkage", "extern" means external linkage.
What should static extern mean? Internal external linkage???

what is the advantage of static function?

see in one project source code i have seen belows declaration
static int *foo();
so it declare foo as static function returning pointer to int. So here i wana ask you whats the purpose of declaring function as static ?
The function's name isn't visible outside the translation unit (source file) in which it's declared, and won't conflict with another function foo in another source file.
In general, functions should probably be declared static unless you have a specific need to call it from another source file.
(Note that it's only the name that's not visible. It can still be called from anywhere in the program via a pointer.)
It prevents other translation units (.c files) from seeing the function. Keeps things clean and tidy. A function without static is extern by default (is visible to other modules).
From the C99 standard:
6.2.2 Linkages of identifiers
If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.
and
In the set of translation units and libraries that constitutes an entire program, each
declaration of a particular identifier with external linkage denotes the same object or
function. Within one translation unit, each declaration of an identifier with internal
linkage denotes the same object or function. Each declaration of an identifier with no
linkage denotes a unique entity.
Declaring a function as static prevents other files from accessing it. In other words, it is only visible to the file it was declared in; a "local" function.
You could also relate static (function declaration keyword, not variable) in C as private in object-oriented languages.
See here for an example.
Marking a function or a global variable as static makes it invisible to the linker once the current translation unit is compiled into an object file.
In other words, it only has internal linkage within the current translation unit. When not using static or explicitly using the extern storage class specifier, the symbol has external linkage.

What is the difference between static int a and int a? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Difference between 'global' and 'static global'
What is the difference between statements 1 and 2 :-
#include <stdio.h>
//In the global declaration area
static int a; // 1.
int b; // 2.
Thanks for help.
A static global variable is local to the translation unit it is defined in. So, if you define static int a; in two different translation units, this will create two independent variables. If you define a non-static global variable int b; in two translation units, you will experience a linker error (but you can use extern int b; in one of the two translation units to tell the linker that it should use the global variable from the other translation unit).
Both are variable definitions, however, the static keyword applied to a variable in the "global declaration area" restricts that global variable to be seen only in the translation unit in which it is defined.
They are both in memory for the entire lifetime of the program. The variable that is declared static only has scope in the file in which it is declared where as the variable declared without static can be accessed from other files using an extern declaration.
Original source - http://bytes.com/topic/c/answers/860211-global-variable-static-global-variable
static int a is only accessible within that file. int b can be accessed with extern int b from a different file.
static int a;
int b;
a has internal linkage. b has extern linkage.
C99 6.2.2
6.2.2 Linkages of identifiers
1) An identifier declared in different scopes or in the same scope more than once can be
made to refer to the same object or function by a process called linkage. There are
three kinds of linkage: external, internal, and none.
2) In the set of translation units and libraries that constitutes an entire program, each
declaration of a particular identifier with external linkage denotes the same object or
function. Within one translation unit, each declaration of an identifier with internal
linkage denotes the same object or function. Each declaration of an identifier with no
linkage denotes a unique entity.
3) If the declaration of a file scope identifier for an object or a function contains the storage-
class specifier static, the identifier has internal linkage.
A static variable's life extends across the lifetime of the program. However, scope rules still apply.
If you define your static variable outside of a method (normally at the beginning of the class) your variable will be available from anywhere within that class.
You can't change the value of these objects. They're normally used for storing things like API keys.

Resources