Using a variable in a file with extern keyword which is defined as static as well as global in the base file?
Asked Answered
A

1

0

Can we use a variable in a file using extern which is defined as both static as well as global in the base file?

Achromaticity answered 4/7, 2020 at 13:7 Comment(1)
I don't think I understand the question. Can you give an example?Blur
T
2

You can't extern-redefine a static variable, though you can extern-redeclare it.

WRONG:

 //filescope
 static int x = 42;
 extern int x = 43; //WRONG

CORRECT:

 //filescope
 static int x = 42;
 extern int x; //redeclares the previous STATIC x (no linkage)

extern doesn't declare a linkage-having identifier with external linkage: it (re)declares the identifier with its previous linkage (external or internal) unless there was no such previous declaration or the declaration didn't have linkage (non-static locals have no linkage).

6.2.2p4:

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) 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.

I wouldn't try to push this behavior with complex overshadowing, though, because neither gcc and clang like extern-redeclarations of an inner static and if you have intervening auto variables between a global static and an innermost extern redeclaration, then the innermost identifier will have conflicting linkage, which results in undefined behavior as per 6.2.2p7 (Thanks to Eric Postpischil for pointing this out).

accepted by gcc and clang:

#include <stdio.h>
static int x = 42;
extern int x;
int main()
{
    extern int x;
    printf("x=%d\n", x); //42
}

accepted by clang only (technically UB due to conflicting linkage)

#include <stdio.h>
static int x = 42;
extern int x;
int main()
{
    int x = 1000;
    printf("x=%d\n", x); //1000
    {
        extern int x; //conflicting (external) linkage
        //=> undefined behavior due to http://port70.net/~nsz/c/c11/n1570.html#6.2.2p7
        printf("x=%d\n", x); //42 on clang; compile time error on gcc
    }
}

perhaps curiously unaccepted by either:

#include <stdio.h>
static int x = 42;
extern int x;
int main()
{
    static int x = 1000;
    extern int x;
    printf("x=%d\n", x); //1000?
    
}
Tenancy answered 4/7, 2020 at 13:53 Comment(3)
For the example with int x = 1000; inside main, the standard is not ambiguous, and both GCC and Clang are conforming: at the inner extern int x;, only the x of int x = 1000; is visible, since it hides the prior declarations, and so it is the one referred to by 6.2.2 4. The prior declaration, int x = 1000; has no linkage, so the new x has external linkage. Then x has been declared with both internal linkage (by the first static int x = 42 and external (by this new one), for which the standard says the behavior is not defined, so both GCC and Clang conform, since anything does.Irving
Alright. Thanks for explaining. This UB due to conflicting language is disappointing, though. Yet another instance of UB doesn't buy any speed and is perfectly preventable at compile time.Tenancy
@EricPostpischil Thanks. I've edited your info into the answer.Tenancy

© 2022 - 2024 — McMap. All rights reserved.