-
Linkage question
I'm a bit puzzled by the following from chapter 3.5 of the C++ standard:
"The name of a function declared in block scope, and the name of an object declared by a block scope extern declaration,
have linkage. If there is a visible declaration of an entity with linkage having the same name and type, ignoring entities
declared outside the innermost enclosing namespace scope, the block scope declaration declares that same entity and
receives the linkage of the previous declaration. If there is more than one such matching entity, the program is ill-formed.
Otherwise, if no matching entity is found, the block scope entity receives external linkage.[ Example:
Code:
static void f();
static int i = 0; // 1
void g() {
extern void f(); // internal linkage
int i; // 2: i has no linkage
{
extern void f(); // internal linkage
extern int i; // 3: external linkage
}
}
There are three objects named i in this program. The object with internal linkage introduced by the declaration in
global scope (line //1 ), the object with automatic storage duration and no linkage introduced by the declaration on line
//2, and the object with static storage duration and external linkage introduced by the declaration on line //3. —end
example ]"
On the basis of the above explanation, I would have expected the object declared in line //3 to be the same one that is defined in line 1//. Can anyone enlighten me as to why it isn't? Also, if they are two different variables, how would you distinguish between them in this translation unit?
Many thanks for any help.
-
It is. External in this case means external to block scope. Notice that extern int i; is within a block, while the int i; that it links to is declared otuside tha block, hence it is external (to the block) linkeage. This is part of the standard to resolve any ambiguities, the example code is extremely poor code to begin with, the standard just defines how it must be dealt with, since it isnt exactly incorrect. The C/C++ standard is a lot like the national electrical code. 99% of it may seem silly because it deals with things that will mostly never come up, but it is there to deal with those oddball situations when they arrise, so there are no amiguities concerning what is and is not proper.
-
Thanks. That's what I thought.
But I would understand the statement "There are three objects named i in this program. etc." to mean that there are three different objects and hence that the first and the third are not the same.
-
So the following program:
Code:
#include <iostream>
static int i = 2;
int main() {
int i = 3;
{
extern int i;
std::cout << "This i: " << i << std::endl;
}
std::cout << "This i: " << i << std::endl;
return 0;
}
which seems roughly analogous to the code in the standard, doesn't compile -- no suitable extern declaration for the third i is found.
I would guess the keyword is "visible"; the static int i declaration is not visible, i.e., not in scope (the declaration of the automatic variable removes the entire block from the scope of the static object), and extern must refer to a variable with linkage, and automatic variables have no linkage.
(Edit: Well, it compiles, but it doesn't link.)
-
It compiles and runs without any problem on my machine:
This is i: 2
This is i: 3
Would the extern keyword not 'unhide' the global i?
-
Well, that's interesting. It compiles and links on my Windows machine, but I cannot get my Mac (with gcc 4.0 and gcc 4.2) to link this program. extern int i is just a declaration, not a definition, so that can't get us into trouble.
Edit: Comeau's online compiler says:
Code:
"ComeauTest.c", line 6: error: external/internal linkage conflict with previous
declaration
extern int i;
^
which makes life even more fun.
-
I get a warning "line 2 : 'i' defined but not used". However, if I delete line 2 and put in another translation unit, the compiler doesn't give any warning.