tags:

views:

349

answers:

7

The way I've always organized my C source was to put struct, macro and function prototypes in header files and function implementations in .c files. However, I have recently been reading alot of other peoples code for large projects and I'm starting to see that people often define things like structs and macros in the C source itself, immediately above the functions that make use of it. I can see some benefit to this as you don't have to go searching around to find the definition of structs and macros used by particular functions, everything is right there in roughly the same place as the functions that use it. However I can also see some disadvantages to it as it means that there is not one central repository for struct/macro definitions as they're scattered through the sourcecode.

My question is, what are some good rules of thumb for deciding when to put the macro/struct definition in the C source code as opposed to the header files themselves?

+17  A: 

Typically, everything you put in the header file is part of the interface, while everything that you put in the source file is part of the implementation.

That is, if something in the header file is only ever used by the associated source file, it's an excellent candidate for moving to that source file. This prevents "polluting" the namespace of every file that uses your header with macros and types that they were never intended to use.

John Calsbeek
+3  A: 
  • stuff defining the external interface to the module goes in the header.
  • stuff just used within the module should stay in the C file.
  • header files should include required headers to support its declarations
  • headers should wrap themselves in #ifndef NAME_H to ensure a single inclusion per compilation unit
  • modules should include their own headers to ensure consistency

Lots of people don't know this basic stuff BTW, which is required to maintain your sanity on any sized C project.

pixelbeat
Good point about including their own header files - I can't believe how often I come across code that doesn't do this, and stupid little differences creep in as a result.
Michael Burr
+3  A: 

Mainly, the issue at hand is a sort of encapsulation consideration. You can think of a module's header file as not so much its "overhead", which is what you seem to be doing now, as its public interface declaration, which is presumably how the people whose code you're looking at are seeing it.

From there it follows naturally that what goes in the header file is things that other modules need to know about: prototypes for functions you anticipate being used externally, structs and macros used for interface purposes, extern variable declarations, and so on, while things that are strictly for the module's internal use go in the .c file.

chaos
+1  A: 

In the book "C style: Standards and Guidelines" from David Straker (available online here), there are some good ideas on file layout, and on the division between C file and headers.

You may read the chapter 7 and specially chapter 7.4.

And as John Calsbeek said, you can based your organization on how the header parts are used. If one structure, type, macro, ... is only used by one source, you can move your code there.

You may have header files for the prototypes and some header file for the common declarations (type definitions, etc...)

ThibThib
+1  A: 

If you define your structs and macros inside the .c, you won't be able to use it from other .c files

To do so, you have to put it in the .h so that #include tells the compiler where to check for your structs and macros

unless you #include "x.c", which you shouldn't do =)

Eric
+3  A: 

Put your public structures and interface into the .h file.

Put your private bits into the .c file.

If I have more than one .c file that implements a logical set of functionality, I'll put the things that need to be shared among those implementation files into a *p.h file ('p' for private). Client code should not include the *p.h header.

For example, if I have a set of routines that implement an XML parser, I might have the following organization:

xmlparser.h    - the public structures, types, enums, and fucniton prototypes

xmlparserp.h   - private types, fuction protoypes, etc. that client code 
                 doesn't and shouldn't need

xmlparser.c    - implementation of the XML parser
xmlutil.c      - some other impementation bits (would include xmlparserp.h)
Michael Burr
+4  A: 

Interfaces and implementations is what it's all about.

Addendum to the accepted answer: it can be useful to put an incomplete struct declaration in the header but put the definition only in the .c file. Now a pointer to that struct gives you a private type that you have complete control over. Very useful to guarantee separation of concerns; a bit like private members in C++.

For extensive examples, follow the link.

Norman Ramsey
+1 I do this all of the time.
Anthony Cuozzo