Search code examples
carraysglobal-variablesextern

Behaviour of global variable in C


If I declared array as a global like this:

#include <stdio.h>

char arr[];

int main()
{
    return 0;
}

The compiler generates a warning:

test.c:3:6: warning: array ‘arr’ assumed to have one element [enabled by default]
 char arr[];

But, If I declared array as a global and explicit provide extern keyword like this:

extern char arr[];

int main()
{
    return 0;
}

Then, it's compile fine without warning.

But, By default global variables are extern, then why does first case generated warning?


Solution

  • Beware there is a little confusion in your terms:

    By default global variables are extern

    Not exactly: global variable have external linkage unless they are declared static. In that latter case they have internal linkage.

    External linkage means that the variable may be refered from a different translation unit (another source file) if it is declared extern there. The extern specifier declares that the variable should be defined elsewhere with external linkage.

    That explains your problem:

    char arr[];
    

    is a tentative (incorrect here) definition of a character array with external linkage. As the size is not specified and cannot be deduced from an initializer, it cannot fully define the array. As it is not declared extern and as no complete definition exists in that translation unit, it is an incorrect definition.

    extern char arr[];
    

    on the other hand only declares arr to be a char array, which is assumed to be defined elsewhere, possibly in a different translation unit. The program will be ill formed with no diagnostic required if there is no definition.

    But this is a perfectly correct program:

    #include <stdio.h>
    
    char arr[];  // tentative definition
    
    int main()
    {
        // can use arr here, except for sizeof(arr) which would be an error
        // because only a declaration (not a definition) has been seen to this point
        return 0;
    }
    
    char arr[] = "abcd";  // full definition: the size is deduced to be 5
    

    The tentative definition is only seen as a forward declaration. As the definition exists in the translation unit the compiler is glad with it...