views:

62

answers:

4

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.

+1  A: 

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.

Benoit Thiery
It's unusual to write `C` in cpp files :)
pmg
Oups :-) Thanks...
Benoit Thiery
+3  A: 

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:

  1. Drop the extern keyword in the declaration in the header file. This is BAD!
  2. 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.
harald
3. Do not use global variables at all. This is the better way :)
pmg
Why is it bad to use the `extern` keyword in a header file?
Kedar Soparkar
pmg: Agreed, but that is beside the problem that the original poster was asking about :)
harald
Kedar: It's not bad in itself to use the extern keyword. It is bad to declare variables in header files (without the extern keyword.)
harald
@harald, your comment seems to be in contradiction to your point no. 1
Kedar Soparkar
Kedar: Nope, I say it is bad to remove the extern keyword in the header file.
harald
@harald, ok, got it!
Kedar Soparkar
+1  A: 

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."
pmg
+1: Great answer. By the way, if I want to include `foobar.h` in another source file, shouldn't the function prototype in it also bear the `extern` keyword?
Kedar Soparkar
You're thinking right :) ... but `extern` is already assumed for functions: it's redundant to add it (no harm in doing so)
pmg
A: 

Put the actual int hi in one of your source codes. And then extern will reference to that.

Green Code