1

7.h:

int a

5.c:

#include"7.h"
#include <stdio.h>
int b;
void way();
void way() {
printf("%p\n",&b);
}

6.c:

#include "7.h"
#include <stdio.h>
void way();
int b;
int main(int argc, char const *argv[])
{
way();
printf("%p\n",&b);
return 0;
}

why can i use "gcc -std=c90 5.c 6.c" to compile it successfully!

the result is 0x10288b018 0x10288b018

same address!!!!!!but i don't use extern !why!

but i change "6.c" to :

6.c:

 #include "7.h"
#include <stdio.h>
void way();
int b=8;
int main(int argc, char const *argv[])
{
way();
printf("%p\n",&a);
return 0;
}

5.c to :

#include"7.h"
#include <stdio.h>
int b=5;
void way();
void way() {
printf("%p\n",&a);
}

But the result is :

duplicate symbol _b in:
    /var/folders/sb/dc6wxwf16kl7k1wrhrxjx5j40000gn/T/5-00d5c1.o
    /var/folders/sb/dc6wxwf16kl7k1wrhrxjx5j40000gn/T/6-2b050b.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Arnab Nandy
  • 6,472
  • 5
  • 44
  • 50
  • 1
    C is a very strange and weird language. It has a concept of a "tentative definition", which makes sure everyone is equally confused about when a variable is actually defined. – Kerrek SB Oct 29 '16 at 10:19
  • The file `7.h` has the variable definition `int a` which is bad practice. – Weather Vane Oct 29 '16 at 10:27
  • `int a;` is a global in this case. – Stargateur Oct 29 '16 at 10:42
  • What you are seeing is a "common extension" to the standard C behaviour. It is documented as such in Appendix J of the standard. With your compiler, you get away with not using `extern`, but your code is not strictly portable. You should use `extern` when you declare variables in a header and then ensure that one object file defines the variable. – Jonathan Leffler Oct 29 '16 at 14:27

1 Answers1

2

extern keyword is not necessary. According to C99 standard:

6.7.5.3.17: If the declaration occurs outside of any function, the identifiers have file scope and external linkage.

The difference between your two examples is explained in section 6.9.2.4:

int i1 = 1; // definition, external linkage
int i4;     // tentative definition, external linkage

The standard says that i1 is a definition, while i4 is a tentative definition. Having multiple definitions is an error; having multiple tentative definitions is not.

If an entity has a non-tentative definition, all tentative definitions refer to it; otherwise, multiple tentative definitions refer to the same entity.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • @Elliotyang I wouldn't call it "successful" because one of the definitions is ignored in favor of the other. I think the idea of tentative definitions was not in the C90 standard. – Sergey Kalinichenko Oct 29 '16 at 11:52
  • I find it ! C89/C90 standard (ISO/IEC 9899:1990): 3.7.2 External object definition ! stentative definitions was in the C90 standard. – Elliot yang Oct 29 '16 at 13:26