Compiling the file main.c with:
gcc main1.c -o final
gives me:
/tmp/cc1cwhAP.o: In function `main':
main1.c:(.text+0xb): undefined reference to `hi'
main1.c:(.text+0x15): undefined reference to `hi'
collect2: ld returned 1 exit status
main1.c:
#include <stdio.h>
#include "incl.h"
int main(void)
{
hi = 1;
printf("hi = %d",hi);
return(0);
}
incl.h:
extern int hi;
What am I doing wrong? (Please be verbose with your answers)
Removing the extern
keyword solves the issue, but I want to be able to use the hi
variable in other source files.
,
You’ve told the compiler that there exist a variable called hi
, but you have not actually defined it.
There’s two ways to solve this:
- Drop the
extern
keyword in the declaration in the header file. This is BAD! - Declare the variable in a source file. This can be either the main1.c or another source file, that you link into the program. This is the good way.
,
Let’s forget about header files for a bit (after all their contents are inserted inside source files during compilation and they only exist during pre-processing). They’re only an easy way to use the same code in several source files (think copy/paste). So, in the interest of efficiency, that duplicated code should do nothing; or we risk doing something more than once.
int x; /* puts aside a memory area with space for an int and call it x */
extern int x; /* tell the compiler that x exists and it is an int */
Which of the above does less? That’s the one to put in a header file. But as we’ve told the compiler x
exists, we need to actually define it somewhere. The best place to define it is in a source file.
As header files don’t do anything, they’re pretty much safe to insert into lots of source files.
Now, back to header files. They’re usually linked to a specific source file (through their names: foobar.h is linked to foobar.c). This is a good method to identify where declarations in the header file are defined.
/* foobar.h */
extern int x;
void myfoo(int);
After seeing this header file, I’d expect foobar.c
to contain the definition of x
and myfoo
.
/* foobar.c */
int x; /* global x. BAD BAD BAD */
void myfoo(int alpha) { x = !x; return x ? alpha : 0; }
Why globals are bad?
quote from http://c2.com/cgi/wiki?GlobalVariablesAreBad
Really Bad Reasons to Use Global Variables
- “I’m a slow typist. Globals save me keystrokes.”
- “I don’t want to pass it around all the time.”
,
When you declare a variable extern, it means to the compiler that it will be defined in some c modules and should be found during linking.
You still need to define a global int hi
in one .c file.
Any .c file including your header file will be able to use it.
,
Put the actual int hi
in one of your source codes. And then extern will reference to that.