I'm reading the C Standard N1570 and faced some misunderstanding about linkage. As specified in 6.2.2. Linkages of objects
:
5 If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.
So I guessed that there is no difference between extern
and no storage-class specifier in the declaration of identifiers of objects with file scope.
Let's condider the following example:
test.h
:
#ifndef _TEST_H
#define _TEST_H
int a;
void increment();
#endif //_TEST_H
test.c
:
#include "test.h"
void increment(){
a += 2;
}
main.c
:
#include <stdio.h>
#include "test.h"
int main(int argc, char const *argv[])
{
increment();
printf("a = %d\n", a);
}
Since a
is declared to have external linkage (file scope, no storage class specifier) a = 2
is printed as expected.
So I replaced the declaration of a
to have extern
specifier and expected no difference (according to the 6.2.2#5
I cited above):
test.h
:
#ifndef _TEST_H
#define _TEST_H
extern int a; // <---- Note extern here
void increment();
#endif //_TEST_H
But now the linker complains:
CMakeFiles/bin.dir/main.c.o: In function `main':
main.c:37: undefined reference to `a'
liblibtest.a(test.c.o): In function `increment':
test.c:4: undefined reference to `a'
test.c:4: undefined reference to `a'
collect2: error: ld returned 1 exit status
How does the Standard explain this behavior? Since identifiers have the same linkage in both cases I expected the linker behavior to be the same too.