-4

I have two .c files, one of them has the definition of x, and the other file is using x, as follows:

file1.c:

int x;
//other code...

main.c:

int main(void)
{
    printf("%d", x);
}

Now, when I compile this code, I get the following compilation error message:

In function 'main':

error: 'x' undeclared (first use in this function)

So, if a global variable (in this case x) is 'extern' by default, then why can't main.c file see x?

When I now go to main.c and define x, so that main.c now looks like:

int x=9; //This line was added.

int main(void)
{
    printf("%d",x);
}

And also initialize x in file1.c, the program doesn't compile and I get the following error message:

error: ld returned 1 exit status

So, if main.c can't see x that is in file1.c, then this time what is the problem?

Is this a linking error?

Note that when I add

extern int x;

in main.c, the problem disappears.

  • The first error is a compiler error. The compiler need to know the type of x. The second error is a linker error (ld). The linker sees two different variables with the same name. With `extern int x` the compiler knows, that there is a variable x of type int in another file so no memory is allocated. – Thomas Sablik Jan 03 '18 at 09:00
  • `Now, when I compile this code`..show us the statement. – Sourav Ghosh Jan 03 '18 at 09:01
  • 1
    C is not the same as C++. You understood the issue: you need to explicitly declare `extern int x;` in `main` function or in `main.c`. It is needed because the [C11](https://en.wikipedia.org/wiki/C11_(C_standard_revision)) standard (read [n1570](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)....) requires that. – Basile Starynkevitch Jan 03 '18 at 09:02
  • I still can't get to what this statement means:" If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external."-->What exactly does "linkage is external" mean?? The way I understand it is that when I create a global variable in a file without a 'storage-class specifier ', this mean I can use it in other .c files without having to declare it using 'extern' in those other files. – Alsayed Alsisi Jan 03 '18 at 09:52
  • 1
    No, "external linkage" means that you *can* access it in another file, *if* you declare it `extern` there. The opposite is "internal linkage", where you cannot access it *at all* from other .c files. – Bo Persson Jan 03 '18 at 11:14

2 Answers2

2

Each compilation unit (in this case your individual .c files) is compiled separately. The compiler needs to know the storage class of x in order to handle it, so your first error (undeclared) comes from the compiler not knowing what x is. The compiler does not need to know where x lives.

When you then link your compiled objects together, the linker resolves any external names (including x in main.c if you've marked it extern) and the final executable will then have all its variables in known places. If it finds 2 extern symbols with the same name, then it will fail, giving you your second error (error: ld returned 1 exit status).

lxop
  • 5,796
  • 2
  • 15
  • 31
  • So, what does this mean?? "From the C99 standard: §6.2.2 Linkages of identifiers 3) If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage. 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." – Alsayed Alsisi Jan 03 '18 at 09:31
  • I can't get to what this statement means:" If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external."-->What exactly does "linkage is external" mean?? The way I understand it is that when I create a global variable in a file without a 'storage-class specifier ', this mean I can use it in other .c files without having to declare it using 'extern' in those other files. – Alsayed Alsisi Jan 03 '18 at 09:53
  • No, what that means is that you _can_ use that variable in other .c files, but those files will need to declare the variable so that the compiler knows that the variable exists. When compiling one .c file, the compiler has no idea what is in any other .c file. This is where header files are usually used, to declare the existence of the variable, while it is defined in just one .c file. Better yet, just don't use global variables, it is a bad idea. – lxop Jan 03 '18 at 15:24
1
  1. You must declare you variable in main.c, so the compiler knows about it: extern int x. The compiler said it to you: error: 'x' undeclared

  2. You added the second definition of x in main.c, the first definition you did in file1.c. The linker informed you about ambiguity between two definitions. You could read the error above the line error: ld returned 1 exit status

S.M.
  • 13,389
  • 7
  • 29
  • 39
  • So, what does this mean?? "From the C99 standard: §6.2.2 Linkages of identifiers 3) If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage. 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." – Alsayed Alsisi Jan 03 '18 at 09:32
  • Please read carefully the link that @DevSolar inserted into your question. – S.M. Jan 03 '18 at 09:39
  • I read it, and still can't get to what this statement means:" If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external."..The way I understand it is that when I create a global variable in a file without a 'storage-class specifier ', this mean I can use it in other .c files without having to declare it using 'extern' in those other files. – Alsayed Alsisi Jan 03 '18 at 09:50
  • Use it in other .c files and link it are different terms. – S.M. Jan 03 '18 at 09:57
  • How, if I may ask? – Alsayed Alsisi Jan 03 '18 at 10:06
  • You can access it if you declare it before. – S.M. Jan 03 '18 at 10:08