1

I've recently begun to realize that the use of the "extern" keyword is highly encouraged. Thus I began to wonder if there is anything wrong with the current (extern-less) way I use header files:

main.c:

#include "main.h"
#include "function.h"

int main(void){
    globalvariable = 0;

    testfunction();
    return 0;
}

main.h:

#ifndef MAIN_H_
#define MAIN_H_

int globalvariable;

#endif /* MAIN_H_ */

function.c:

#include "main.h"
#include "function.h"

void testfunction(){
    globalvariable++;
    return;
}

function.h:

#ifndef FUNCTION_H_
#define FUNCTION_H_

void testfunction(void);

#endif /* FUNCTION_H_ */

Thus every new source file that needs access to globalvariable simply needs to include main.h.

One obvious drawback to this method is arrays: you can't use {element0, element1, ...} formatting to assign values to an array once it has been declared.

By the way, when I give globalvariable an initial value of zero, am I defining it at that point? Or is memory allocated earlier?

Also, is there an official term for the method I'm using?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
SharpHawk
  • 378
  • 7
  • 19
  • The `extern` keyword is not highly encouraged; you should use it only when you absolutely must (which hopefully is never). – Oliver Charlesworth Apr 09 '12 at 20:23
  • http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c – cnicutar Apr 09 '12 at 20:24
  • [Global variables are bad](http://c2.com/cgi/wiki?GlobalVariablesAreBad). – Fred Larson Apr 09 '12 at 20:24
  • Interesting. The feeling I'd gotten from previous threads here was that extern was the de facto way of doing things. – SharpHawk Apr 09 '12 at 20:32
  • Well, a quote from the top cnicutar linked to (which I'd read before posting my question) states: "Although there are other ways of doing it, the clean, reliable way to declare and define global variables is to use a header file file3.h to contain an extern declaration of the variable." Oli, are you saying there's a better way of declaring and defining global variables? – SharpHawk Apr 09 '12 at 20:43
  • 1
    @SharpHawk: No (there isn't). I'm implying that you should be avoiding global variables shared between multiple translation units... – Oliver Charlesworth Apr 09 '12 at 20:48
  • Ah, ok. The lack of classes in C was the main reason why I used the global variables that I did. – SharpHawk Apr 09 '12 at 20:58

5 Answers5

2

The drawback of your code is that you will probably get a linker error.1


1. Where "probably" is based on the notion of building your code on a whole bunch of different toolchains.
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
2

The problem with this is that you may get linking errors due to multiple definitions when you try to link your program. You're depending on implementation defined behavior here -- the implementation is allowed to treat the duplicate definitions as all referring to a single object, but is not required to.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
2
extern int globalvariable;

is a declaration

int globalvariable;

is both a declaration and a tentative definition.

In C, it's illegal for the same variable to have multiple definitions, and that will happen if you use the latter in a header file that's included in more than one translation unit.

Unix systems however historically allow this usage, so most compilers will accept the code despite it being invalid C.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • What do you mean by "use the latter in a header file that's included in more than one translation unit"? Would having multiple source files include that header file count? If so, that's exactly what I'm doing, and as you stated in your last line, the compiler doesn't complain. In fact, it doesn't even produce a warning. – SharpHawk Apr 09 '12 at 20:36
  • Right. The compiler can't complain because each individual translation unit is valid; only the linker could complain, and it doesn't, because it's traditional on unix to allow this. That still doesn't make it valid C, and it's not doing what you want. (It's collapsing multiple definitions of the variable into one at link-time rather than declaring that you want to access a variable defined in another translation unit.) – R.. GitHub STOP HELPING ICE Apr 09 '12 at 20:43
2

The only official term that I know of for the method you are using is "implementation dependent behavior". You will run into all sorts of problems with that method once you start building with different compilers (or possibly even different versions of the same compiler). Some will throw a linker error, but some will accept it (although there's no guarantee exactly how it will be interpreted). I highly recommend that you adopt a more standard approach that compilers will interpret in a predictable way.

The definition for a variable needs to be in a .c file. If you want to access that variable from another .c file, add an extern declaration in a header. This technique is standard C and will be interpreted predictably on any conforming compiler.

To answer your allocation question, memory for all globals is allocated before the program starts running. A global variable takes up space even if it is only used in a subsection of the code that never runs. Your globalvariable = 0; line isn't actually giving the variable an initial value. The C compiler will make sure that all uninitialized global variables are automatically initialized to zero when the program loads. Your code is technically re-assigning the variable's value. If you want to make sure that a global is initialized to a particular value, add the initializer to the definition like int globalvariable = 42;.

bta
  • 43,959
  • 6
  • 69
  • 99
  • I was torn between this answer and "R.."'s. This one won out due to answering all parts of my original post. – SharpHawk Apr 10 '12 at 16:26
0

ANSI C standard says

If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.

Inquisitive
  • 475
  • 1
  • 5
  • 13