tags:

views:

101

answers:

4

I don't quite understand how things should be separated in C's source and header files. I often see many projects with two sets of files with the same name (sans the extension denoting source and header files).

So far, from this lack of understanding, when I've written libraries, I've chucked all the class and class method code into one file, with indecision as to choosing the file extension.

What should be in headers and what should be in the source files? How do I implement this separation?

+1  A: 

Usually, header files contain declarations, source files contain code.

So, if in source file A.c you need a function implemented in source file B.c, you just include B.h to have its declaration.

klez
+8  A: 

There is no technical difference. The compiler will happily let you include a .c file, or compile a .h file directly, if you want to.

There is, however, a huge cultural difference:

  • Declarations (prototypes) go in .h files. The .h file is the interface to whatever is implemented in the corresponding .c file.

  • Definitions go in .c files. They implement the interface specified in the .h file.

The difference is that a .h file can (and usually will) be #included into multiple compilation units (.c files). If you define a function in a .h file, it will end up in multiple .o files, and the linker will complain about a multiply defined symbol. That's why definitions should not go in .h files. (Inline functions are the exception.)

If a function is defined in a .c file, and you want to use it from other .c files, a declaration of that function needs to be available in each of those other .c files. That's why you put the declaration in a .h, and #include that in each of them. You could also repeat the declaration in each .c file, but that leads to lots of code duplication and an unmantainable mess.

If a function is defined in a .c file, but you don't want to use it from other .c files, there's no need to declare it in the header. It's essentially an implementation detail of that .c file. In that case, make the function static as well, so it doesn't conflict with identically-named functions in other files.

Thomas
Unfortunately, even though the standard does not mandate anything, most compilers I've used depend to a certain extent on the file extension. Try this: create two files containing (say, `int main(){return 0;}`) called `header.c` and `header.h` and try to compile them with gcc. (I am not even getting anywhere near VS!)
dirkgently
I suspect that most programmers don't put the declarations of static functions in the .h file. The main difference between .h and .c is between interface and implementation.
Dipstick
@dirkgently: Okay, but your compiler is not acting as a C compiler if it doesn't get the right file extension. The standard doesn't say anything about programs that are not C compilers :)
Thomas
@chrisharris: Good point. I'll edit that in.
Thomas
@Thomas: You didn't read my post correctly. The standard says _source_ and _header_ files and does not mandate particular extensions for them as such. And yes, try the snippet I posted with the command line: `gcc -Wall -ansi -pedantic -std=c99 -o header` and see what you get.
dirkgently
A precompiled header, how interesting! Thanks, I learned something today :)
Thomas
Precompiled headers are a must in any project of considerable complexity. Most compilers these days have switches to indicate a particular file that you want to mark for precompilation. Also, they typically need to be included in every source.
dirkgently
+4  A: 

What should be in headers and what should be in the source files?

Typically headers contain one or more of the following:

  • Function declaration (except statics)
  • Variable declaration (typically global)
  • User defined type declaration (read struct, union etc.)
  • Macro definition

Source files on the other hand have:

  • Function/variable definition
  • Static function declaration and definition (you don't want to expose these to your clients)
  • Variable definition
  • Some prefer to define inline functions (C99) in a header

How do I implement this separation?

The One Definition Rule is your friend.

Remember, if you are writing a library, this is what your client gets to see. So, be helpful and provide all the information you can for them to use your library. The source files are typically compiled and supplied in binary form.

And by the way, C does not have the concept of classes.

dirkgently
`struct` is close enough for me :)
Delan Azabani
If "The One Definition Rule" is golden, "Don't tell" is silver. With that I mean is that don't put private details in header files.If you make a 3rd party library, everything you put in the header file you have to support in the future. If you work in large projects minimizing header files promotes refactoring as it will reduce compile time when you actually do need to change the header files.(I have been in a project where it took 12 hours to recompile if you changed central header files. 12hoursx#numberofdevelopers = money. )
FuleSnabel
+1  A: 

There is little fundamental difference between .c and .h files (though some compilers may refuse to compile a raw .h file). The difference is more by convention.

Typically the .h file provides the API and the .c provides the implementation.

Therefore the .h file would contain only things needed by other source files to access the facilities provided by your .c file. So the .h files would provide the function prototypes of global functions, declarations of global variables (if you really must have them), and the structures and other types used by them. (Don't expose a structure if the only a pointer to the structure is required by the API.)

In-line functions are also often included in .h files but some coding guidelines prefer the use of a separate extension (e.g. .inl)

All other function implementations, the definition and initialisation of variables and declarations of local (static) variables and functions would be in the .c file.

Dipstick