Reputation: 4903
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?
Upvotes: 2
Views: 221
Reputation: 149075
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...
Upvotes: 4
Reputation: 399949
The first case needs to allocate memory at run-time for an array of unspecified length. This is "hard", which is why the compiler complains and cheats out by assuming a length of 1.
The second case only needs for someone else to provide a base address for an array, and it's that someone's problem to make sure there's memory allocated at the provided location.
Not entirely sure how the details land, but that's the basic difference between the two.
The C11 draft even has this as an explicit example:
extern int *x;
extern int y[];
The first declares
x
to be a pointer toint
; the second declaresy
to be an array ofint
of unspecified size (an incomplete type), the storage for which is defined elsewhere.
Upvotes: 8
Reputation: 16424
When you write a
char arr[];
in global scope, your intention is to define an array with static lifetime. Thus you must specify how many elements it contains.
When you write
extern char arr[];
it's only a declaration, to tell compiler that an array named arr
exists somewhere else, not defined here. Thus no size is required.
Upvotes: 5