tags:

views:

282

answers:

7

I'm trying to figure this part of C out. I've read some tutorials given to me but I haven't found it yet.

Trying to read libraries I see that there are .c and .h files of the same name. In the main sourcethe .h file is included but not the .c file. When I look at the code in the .h file it also doesn't #include the .c file of the same name. Am I missing something? Does the compiler automatically include a .c file when a .h file of the same name is #include'd?

+6  A: 

No. There's no need to include .c files in .h files. .h files are not normally passed as compiler input directly but their sole purpose is to be included by other files.

Usually, it's something like:

"a.c"    includes   "a.h"
"b.c"    includes   "c.h"

You compile "a.c" and "b.c" and link the output files.

Mehrdad Afshari
+3  A: 

The .h file contains the declarations of the functions in the .c file. These declarations are needed by other .c files that want to use functionality of another .c file. So .c files are never included by .h files.

Each of the .c files is compiled into an object file and all those object files are then linked together into libraries or applications.

jackrabbit
+8  A: 

Typical .h files serve as a "table of contents" for the .c file, including such things as function prototypes, typedefs and the like. Programs include the .h so that they know about the functions and types.

The .c files are compiled separately and product object files (.o or .obj) that contain the actual code.

The object files are then tied to the main program through a Makefile, Project file, or similar method. Then the object files are linked with the main program, producing a functional whole.

In the case of libraries, there is no main program. The object files are gathered together and put in a special format (for static or dynamic libraries). Any program using the library would include the .h as above, and link against the library.

dwc
+1  A: 

The preprocessor doesn't do anything magical.

To include something within an included directory (hard to do with your own headers)

#include <foo.h>

or to include something within the same compilation directory

#include "foo.h"

All it does it take the text of foo.h and plug it directly in to the output. gcc a.c -E will print out what it looks like after preprocessing.

It's a 'dumb' process in that writing your own program that will handle #include correctly is kind of a trivial exercise.

Alex Gartrell
+3  A: 

There is no magic. When a C program is compiled, there are two major steps to it.

First, each individual compilation unit is compiled in is isolation. (A compilation unit is basically one .c file, plus everything it includes).

At this stage, it doesn't know anything about what's contained in other .c files, which means that it can't generate a full program. What it can do is generate code with a few "fill in the blanks" spots. If, from foo.c you call a function that is declared in bar.h, and defined in bar.c, then the compiler can only see that the function exists. It is declared in bar.h, so we have to assume that the full definition exists somewher. But because that definition is inside another compilation unit, we can't yet see it. So the compiler generates code to call the function, with a little note on it saying "fill in the address of this function once it's actually known".

Once every compilation unit has been compiled in this way, you are left with a bunch of object files (typically .o if compiled by GCC, and .obj if you use MSVC), containing this kind of "fill in the blanks" code.

Now the linker takes all these object files, and tries to merge them together, which allows it to fill in the blanks. The function we generated a call for above can now be found, so we can insert its address into the call.

So nothing special happens if a .c file has the same name as a .h. That's just a convention to make it easier for humans to figure out what's inside each file.

The compiler doesn't care. It just takes each .c file, plus anything it includes, and compiles it to an object file. And then the linker merges all these object files together into a single executable.

jalf
+1  A: 

G'day,

There's a bit of a misnomer in your question. You compile aginst *.h files and, disregarding inlines, you link against *.c files.

If you go back to basics you can say that:

  • the ".h" file is your interface to the library, i.e. what you have to compile against, and
  • the matching *.c file is the implementation of what you intend the function to do.

So, as an example:

  1. a file add_integers.h just declares the function, say addInts(), that takes two integers and returns an integer that is the sum of the two, and
  2. a a file add_integers.c(pp) provides the implementation of the function addInts() that uses an algorithm that taking two integers, adds them together, and returns the results.

The implementor of the addInts() function is free to make modifications to the software that implements the addInts() function.

Providing the interface to the addInts() function isn't modified at all (i.e. addInts.h isn't modified at all), then a new shared library containing the modified implementation of the addInts function is free to be distributed without people having to recompile against the new addInts library release.

Wow! Why does reading this explanation sound like Danny Kaye and "The Vessel with the Pessel"?

You might like to have a look at Bertrand Meyer's work with Eiffel and "Design by Contract".

HTH

cheers,

Rob Wells
A: 

If I want to make a static library in C or C++ I will put my functions prototypes in the .h and the actual functions codes in the .c or .cpp. After that I compiled my .cpp to make a .lib

To link my .h to my .lib I write this preprocessor command in the .h

pragma comment (lib, "theNameOfTheLibFile.lib")

After that if I include the .h in a program, my program knows where to find the matching library.

Joel