Nigel Ridley
Nigel Ridley

Reputation: 323

Duplicate header files throughout source files?

// File foo1.c :
#include <stdio.h> // once
void foo1(void);
void foo1(void){
    puts("foo1");
}

// File foo2.c :
#include <stdio.h> // again
void foo2(void);
void foo2(void){
    puts("foo2");
}

// File foomain.c :
#include <stdio.h> // yet again
void foo1(void); // again
void foo2(void); // again
int main(void){
    foo1();
    foo2();
    puts("foomain");
    return 0;
}

// create object files
gcc -fPIC foo1.c -o foo1.o // 1 stdio.h
gcc -fPIC foo2.c -o foo2.o // 1 stdio.h

// create shared library
gcc -fPIC -shared foo1.o foo2.o -o foo.so // foo.so contains stdio.h 2 times ?

// build entire program
gcc foo.so foomain.c -o foomain // foomain contains 1 stdio.h plus the 2 from foo.so ?
  1. Why does the entire program contain 3 stdio.h ? Seems redundant, why not just 1 ? Shouldn't the compiler need only 1 ?

  2. It makes sense for the object files to contain a prototype but why do they have to be specified again in foomain.c ? Shouldn't the compiler know they are already specified in foo.so ?

Upvotes: 3

Views: 3404

Answers (4)

parallelgeek
parallelgeek

Reputation: 448

That's because each file is compiled separately, so each time the compiler should know the signatures of all functions used to perform compile-time checks. So, each file has to contain all declarations used, which are included by the preprocessor before the file is compiled.

Upvotes: 8

Some programmer dude
Some programmer dude

Reputation: 409482

The #include lines are not actually a part of the compiler, but the C preprocessor.

What the preprocessor does with #include lines is to actually include the file into the source, and creates a new temporary file containing the contents of your file with the #include line replaced by the contents of the file being included.

You don't actually need the include file at all, if all you are doing is calling functions. You might get warnings about the functions not being declared, but those can be adding the prototypes for those functions yourself. For example, in your main source file you only use puts, instead of including <stdio.h> you can add a prototype like this:

int puts(const char *s);

However, <stdio.h> also defines some structures (like the FILE structure) and declares some variables (like stdout) and if you use any of those you need the header file as well.

Upvotes: 2

Tony The Lion
Tony The Lion

Reputation: 63310

You can use include guards as @Jeff suggested or just put #pragma once at the top of each header.

Upvotes: 0

Jeff Foster
Jeff Foster

Reputation: 44746

If you look at the top of most header files they have an include guard to stop double inclusion.

#ifndef FOO
#define FOO

#endif

See Include Guard for more information.

Upvotes: 3

Related Questions