Search code examples
cstaticcompiler-errorsdeclarationextern

the memory location of static and extern storage class in C


I have two files which are sharing the global variables.

In main.c

#include<stdio.h>
static int b;
extern int b;
main()
{
extern int a;
printf("a=%d &a:%p\n",a,&a);
printf("b=%d &b:%p\n",b,&b);
fn();
}

In fun.c

#include<stdio.h>
int b=25;
int a=10;
fn()
{
printf("in fna=%d &a:%p\n",a,&a);
printf("in fnb=%d &b:%p\n",b,&b);
}

If I compile both files. I'm not getting any compilation error. And its fine.The output is

a=10 &a:0x804a018 b=0 &b:0x804a024 in fna=10 &a:0x804a018 in fnb=25 &b:0x804a014

But, in main.c if I alter the lines extern int b and static int b like this

#include<stdio.h>
extern int b;
static int b;
main()
{
extern int a;
printf("a=%d &a:%p\n",a,&a);
printf("b=%d &b:%p\n",b,&b);
fn();
}

At compilation, I'm getting this error.

main.c:6:12: error: static declaration of ‘b’ follows non-static declaration main.c:5:12: note: previous declaration of ‘b’ was here

Here the issue is with memory at which static and extern variables are stored. But I couldn't able to conclude the exact reason why is the compilation error at second time

Note: I'm using gcc compiler.


Solution

  • These two quotes from the C Standard (6.2.2 Linkages of identifiers) will help to understand the problem.

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

    and

    7 If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.

    In this translation unit

    #include<stdio.h>
    static int b;
    extern int b;
    main()
    {
    extern int a;
    printf("a=%d &a:%p\n",a,&a);
    printf("b=%d &b:%p\n",b,&b);
    fn();
    }
    

    indentifier b has internal linkage (read the first quote). The first declaration of b declares the identifier as having the internal linkage due to the storage-calss specifier static. The second declaration of b with the storage-class specifier extern has prior declaration of b (the first declaration) with the the storage class specifier static. So the linkage of the identifer is the same as the linkage of the prior declared identifier.

    In this translation unit

    #include<stdio.h>
    extern int b;
    static int b;
    main()
    {
    extern int a;
    printf("a=%d &a:%p\n",a,&a);
    printf("b=%d &b:%p\n",b,&b);
    fn();
    } 
    

    identifier b is declared as having external and internal linkage (read the both quotes). So the compiler issues the message.

    At first the identifier b was declared as having external linkage (because there is no prior declaration with a given linkage) And then due to the specifier static the same identifier is declared as having internal linkage.