简体   繁体   中英

Is it valid to use extern in a local scope to unshadow a global variable?

Is this extern declaration in a nested local scope a valid and defined way to bring the global a back into the scope?

int a = 1; // may be in another file
void main() {
    int a = 2; // hides the global
    {
     cout << a << endl;  // prints 2
     cout << ::a << endl; // obviously 1
     extern int a;
     cout << a << endl;  // also prints 1
    }
}

This is a valid use of extern , though an obscure one. According to the C++20 standard ([basic.link]/6):

The name of a function declared in block scope and the name of a variable declared by a block scope extern declaration have linkage. If such a declaration is attached to a named module, the program is ill-formed. If there is a visible declaration of an entity with linkage, ignoring entities declared outside the innermost enclosing namespace scope, such that the block scope declaration would be a (possibly ill-formed) redeclaration if the two declarations appeared in the same declarative region, 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. If, within a translation unit, the same entity is declared with both internal and external linkage, the program is ill-formed.

In the OP's example, the block-scope declaration extern int a; fails to find a matching declaration with linkage, because the local declaration int a = 2; which has no linkage hides the global declaration int a = 1; which has external linkage. Therefore, extern int a; defaults to external linkage. Also see paragraph 7:

When a block scope declaration of an entity with linkage is not found to refer to some other declaration, then that entity is a member of the innermost enclosing namespace. However such a declaration does not introduce the member name in its namespace scope.

Therefore, extern int a; declares a as a member of the nearest enclosing namespace, which is the global namespace. This means it's the same entity as the previously declared global a , since both declare a variable with the same name in the same namespace with linkage. In other words, it gives you a way to refer to the global variable within the block.

This use of extern was inherited from C, but it is obscure even in C. Its use should generally be avoided in favour of ::a .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM