Search code examples
c++variablesstorageone-definition-rule

Declaring the same variables name within a given same scope in C++


I'm trying to understand Storage class specifiers in C++. I have a two cases.

Here, Within a given same scope, declaring the same variables name.

Case 1:

#include <iostream>

static int i; 
extern int i; 

int main() {
    std::cout<<i<<std::endl;
    return 0;
}

Output:

0

Case 2:

#include <iostream>

extern int i; 
static int i; 

int main() {
    std::cout<<i<<std::endl;
    return 0;
}

Getting an error:

prog.cpp:4:12: error: 'i' was declared 'extern' and later 'static' [-fpermissive]
 static int i; 
            ^
prog.cpp:3:12: note: previous declaration of 'i'
 extern int i;

Why does first case working fine whereas second case give an error?


Solution

  • extern is a little peculiar, in that a declaration marked with it looks for a previous declaration of the same entity, and if it finds one, it uses the previous linkage. Only if it doesn't find one does it declare a new entity with external linkage.

    static, on the other hand, unconditionally declares its entity with internal linkage.

    This means that this code simply declares and defines i with internal linkage. The second declaration finds the first and reuses its linkage.

    static int i;
    extern int i;
    

    Whereas this code declares the variable to have external linkage, and then declares and defines it to have internal linkage, which is an error.

    extern int i;
    static int i;
    

    The reasons for this behavior are hard to track, but most likely reach back way to the pre-standard days of C.

    In C++, this behavior is specified by [basic.link], 6.5/6 in the most recent draft N4687:

    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 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.