views:

436

answers:

9

Is it necessary to #include some file, if inside a header (*.h), types defined in this file are used?

For instance, if I use GLib and wish to use the gchar basic type in a structure defined in my header, is it necessary to do a #include <glib.h>, knowing that I already have it in my *.c file?

If yes do I also have to put it between the #ifndef and #define or after the #define?

A: 

Usually, library developers protect their includes from multiple including with the #ifndef /#define / #endif "trick" so you don't have to do it.

Of course, you should check... but anyways the compiler will tell you at some point ;-) It is anyhow a good practice to check for multiple inclusions since it slows down the compilation cycle.

jldupont
A: 

Just include all external headers in one common header file in your project, e.g. global.h and include it in all your c files:

It can look like this:

#ifndef GLOBAL_GUARD
#define GLOBAL_GUARD

#include <glib.h>
/*...*/
typedef int  YOUR_INT_TYPE;
typedef char YOUR_CHAR_TYPE;
/*...*/
#endif

This file uses include guard to avoid multiple inclusions, illegal multiple definitions, etc.

psihodelia
I would rather name it something like <projectname>.h or something, but make sure to note that if your including a lot of files, it can really slow down the total compilation time.
Earlz
I think however, that global.h is ok. I have seen such convention in many serious projects.
psihodelia
This is OK if by external headers you mean outside the current project and ones that won't change often. If it is used to include all headers outside the current module/library it will cause a lot of unnecessary re-compilation when one header is changed that is not required for all source files.
danio
Very good idea, but you tell me to include it in .c or .h <u>or</u> files which doesn't really answer my question. I put it once in the .c file. It doesn't seem necessary for the compiler to do it in the .h too.
Victor
+10  A: 

A good practice is to only put #includes in an include file if the include file needs them. If the definitions in a given include file are only used in the .c file then include it only in the .c file.

In your case, i would include it in the include file between the #ifdef/#endif.

This will minimize dependencies so that files that don't need a given include won't have to be recompiled if the include file changes.

Richard Pennington
Bad advice. It will produce ugly C program (with #ifdef/#endif).
psihodelia
I think you misunderstood my answer. It is common practice to use #ifdef/#endif in .h files to avoid multiple includes of a .h file.
Richard Pennington
That's what i read on the gnu site. But what's the difference between #include placed before #define (and after the #ifndef) and after the #define?
Victor
No difference to the preprocessor as the statement will always get executed if the file has not been included yet. However you should not put anything between the #ifndef and the #define as it is a common pattern other programmers will be used to seeing.
danio
A: 

During compilation preprocessor just replaces #include directive by specified file content. To prevent endless loop it should use

#ifndef SOMEIDENTIFIER
#define SOMEIDENTIFIER
....header file body........
#endif

If some header was included into another header which was included to your file than it is not necessary to explicitly include it again, because it will be included into the file recursively

Alex
A: 

Yes it is necessary or the compiler will complain when it tries to compile code that it is not "aware" of. Think of #include's are a hint/nudge/elbow to the compiler to tell it to pick up the declarations, structures etc in order for a successful compile. The #ifdef/#endif header trick as pointed out by jldupont, is to speed up compilation of code.

It is used in instances where you have a C++ compiler and compiling plain C code as shown here Here is an example of the trick:

#ifndef __MY_HEADER_H__
#define __MY_HEADER_H__

#ifdef __cplusplus
extern "C" {
#endif


/* C code here such as structures, declarations etc. */

#ifdef __cplusplus
}
#endif

#endif /* __MY_HEADER_H__ */

Now, if this was included multiple times, the compiler will only include it once since the symbol __MY_HEADER_H__ is defined once, which speeds up compilation times. Notice the symbol cplusplus in the above example, that is the normal standard way of coping with C++ compiling if you have a C code lying around.

I have included the above to show this (despite not really relevant to the poster's original question). Hope this helps, Best regards, Tom.

PS: Sorry for letting anyone downvote this as I thought it would be useful tidbit for newcomers to C/C++. Leave a comment/criticisms etc as they are most welcome.

tommieb75
The ANSI C compiler doesn't complain about usage within headers of types defined elsewhere.
Victor
@Victor: True, but if you only have a C++ compiler, this will enable the C++ compiler to compile plain old C fashioned code...hope this clarifies my point. Thanks for your comment anyway. :)
tommieb75
Using double-underscore in your code is a bad idea; all names using double underscore reserved for the implementation in C++, and names starting with double underscore are reserved for the implementation in C.
Jonathan Leffler
__cplusplus is a macro defined by the implementation if it is a c++ compiler, although you are correct for the include guard define
Scott Wales
A: 

You need to include the header from your header, and there's no need to include it in the .c. Includes should go after the #define so they are not unnecessarily included multiple times. For example:

/* myHeader.h */
#ifndef MY_HEADER_H
#define MY_HEADER_H

#include <glib.h>

struct S
{
    gchar c;
};

#endif /* MY_HEADER_H */

and

/* myCode.c */
#include "myHeader.h"

void myFunction()
{
    struct S s;
    /* really exciting code goes here */
}
danio
so if i #include the glib.h in the header i don't need to do it in the .c file? I'm using GLib types and functions in the .c too!
Victor
Yes - because the .c includes the .h which includes glib.h so effectively including glib.h in the .c
danio
As long as that header is then included in the .c file, yes - all include does is insert the contents of the file at compile time. So they get copied from glib.h to myheader.h which then copies them into mycode.c
Martin Beckett
+9  A: 

NASA's Goddard Space Flight Center (GSFC) rules for headers in C state that it must be possible to include a header in a source file as the only header, and that code using the facilities provided by that header will then compile.

The benefit of this rule is that if someone needs to use the header, they do not have to struggle to work out which other headers must also be included - they know that the header provides everything necessary.

The possible downside is that some headers might be included many times; that is why the multiple inclusion header guards are crucial (and why compilers try to avoid reincluding headers whenever possible).

Implementation

This rule means that if the header uses a type - such as 'FILE *' or 'size_t' - then it must ensure that the appropriate other header (<stdio.h> or <stddef.h> for example) should be included. A corollary, often forgotten, is that the header should not include any other header that is not needed by the user of the package in order to use the package. The header should be minimal, in other words.

Further, the GSFC rules provide a simple technique to ensure that this is what happens:

  • In the source file that defines the functionality, the header must be the first header listed.

Hence, suppose we have a Magic Sort.

magicsort.h

#ifndef MAGICSORT_H_INCLUDED
#define MAGICSORT_H_INCLUDED

#include <stddef.h>

typedef int (*Comparator)(const void *, const void *);
extern void magicsort(void *array, size_t number, size_t size, Comparator cmp);

#endif /* MAGICSORT_H_INCLUDED */

magicsort.c

#include <magicsort.h>

void magicsort(void *array, size_t number, size_t size, Comparator cmp)
{
    ...body of sort...
}

Note that the header must include some standard header that defines size_t; the smallest standard header that does so is <stddef.h>, though several others also do so (<stdio.h>, <stdlib.h>, <string.h>, possibly a few others).

Also, as mentioned before, if the implementation file needs some other headers, so be it, and it is entirely normal for some extra headers to be necessary. But the implementation file ('magicsort.c') should include them itself, and not rely on its header to include them. The header should only include what users of the software need; not what the implementers need.

Configuration headers

If your code uses a configuration header (GNU Autoconf and the generated 'config.h', for example), you may need to use this in 'magicsort.c':

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */

#include "magicsort.h"

...

This is the only time I know of that the module's private header is not the very first header in the implementation file. However, the conditional inclusion of 'config.h' should probably be in 'magicsort.h' itself.

Jonathan Leffler
Thanks, that answers my question. Just a detail:what the difference between#define MAGICSORT_H_INCLUDEDand#define MAGICSORT_H_INCLUDED <b>1</b>
Victor
Sorry wanted to have 1 bolded.
Victor
There's no operational difference. Using `#define X` with no value specified means that X evaluates to an empty string except in a conditional context like `#if X` where it evaluates to 0; obviously, `#define X 1` always expands to 1. As long as you always test with `#ifdef X` (or `#if defined(X)` or `#elif defined(X)`) and not with `#if X`, then you are fine with either.
Jonathan Leffler
@Victor: if you find a comment doesn't format as you expected, I copy the text, delete the original comment (as long as it has no up votes), and then submit a new comment with the correct formatting. However, be aware that you can only submit one comment every 30 seconds.
Jonathan Leffler
Well answered! +1
Norman Ramsey
+1  A: 

I use the following construct to be sure, that the needed include file is included before this include. I include all header files in source files only.

#ifndef INCLUDE_FILE_H
 #error "#include INCLUDE.h" must appear in source files before "#include THISFILE.h"
#endif
Thomas Weber
A: 

What I normally do is make a single include file that includes all necessary dependencies in the right order. So I might have:

#ifndef _PROJECT_H_
#define _PROJECT_H_
#include <someDependency.h>
#include "my_project_types.h"
#include "my_project_implementation_prototypes.h"
#endif

All in project.h. Now project.h can be included anywhere with no order requirements but I still have the luxury of having my dependencies, types, and API function prototypes in different headers.

Andrew Myers