Header files included in header files

J

John Smith

Hi all

What does the group think of the practise of including one header file from
inside another?

I have some legacy code where this has been done, and it creates a
dependency on a module (collection of files) which are not required, except
for one header file's contents.

I'd say 'No, header files should be included in the C source, not in another
header', but I've always come across strong arguments for the latter.

What do you think, and what is accepted practise?

Thanks
JS
 
C

Christian Bau

"John Smith said:
Hi all

What does the group think of the practise of including one header file from
inside another?

I have some legacy code where this has been done, and it creates a
dependency on a module (collection of files) which are not required, except
for one header file's contents.

I'd say 'No, header files should be included in the C source, not in another
header', but I've always come across strong arguments for the latter.

What do you think, and what is accepted practise?

If you write a header file "header.h", then it must be written in such a
way that the single line source file

#include "header.h"

compiles without errors. That means header.h needs to include everything
that is necessary to make this work, but not more.

Note that a function can have arguments or return values of type "struct
xxx *" without having the declaration of struct xxx around; this feature
of C often makes it unnecessary to include header files within header
files.
 
J

John Smith

Christian Bau said:
If you write a header file "header.h", then it must be written in such a
way that the single line source file

#include "header.h"

compiles without errors. That means header.h needs to include everything
that is necessary to make this work, but not more.

Note that a function can have arguments or return values of type "struct
xxx *" without having the declaration of struct xxx around; this feature
of C often makes it unnecessary to include header files within header
files.

Thanks Christian

You have a good point about it having to compile. This particular header
problem has, in the first header, something like
typedef struct
{ int array[THIS_IS_DEFINED_IN_HEADER2]; } astruct;

and of course in the other header
#define THIS_IS_DEFINED_IN_HEADER2 5

This turns out to be the only dependant thing!
Normal practise, or poor coding?

Thanks
JS
 
M

Michael Mair

Hi John,

You have a good point about it having to compile. This particular header
problem has, in the first header, something like
typedef struct
{ int array[THIS_IS_DEFINED_IN_HEADER2]; } astruct;

and of course in the other header
#define THIS_IS_DEFINED_IN_HEADER2 5

This turns out to be the only dependant thing!
Normal practise, or poor coding?

It depends. I am working with a huge code where you have hundreds
of header files. Many of the THIS_IS_DEFINED_IN_HEADER2 type
symbolic constants make sense insofar as you then can assume
that all arrays (in your example) serving a certain purpose
are of the same size -- the advantages are clear, I think.

On the other hand, if this symbolic constant does not have
a "deeper" meaning for the purpose of your array but only has
per chance the value 5 which you also have as the array size,
then it is poor coding.

If you are sure about the implications, you can also use a
construct like

#ifndef DONTWANNAINCLUDEIT
#include "header2.h"
#endif

#ifdef THIS_IS_DEFINED_IN_HEADER2
#define MY_ARRAY_SIZE THIS_IS_DEFINED_IN_HEADER2
#else
#define MY_ARRAY_SIZE 5
#endif

typedef struct {
int array[MY_ARRAY_SIZE];
} astruct;


Cheers,
Michael
 
E

Emmanuel Delahaye

John Smith a couché sur son écran :
What does the group think of the practise of including one header file from
inside another?

This group is made of individuals fitted with free will (well, I guess)
and free speech (this, I know!). It may have some consensus on certain
points, but don't expect some 'unique way of thinking' from this group.
It's not a sectarian group. It's an open and free community. Expression
is individual.
I have some legacy code where this has been done, and it creates a
dependency on a module (collection of files) which are not required, except
for one header file's contents.

Sounds like a design issue.
I'd say 'No, header files should be included in the C source, not in another
header', but I've always come across strong arguments for the latter.

Heavy rules are raley useful. Better to act according to the situation.

That said, here are some basics (call them rules if you want):

- A header should be guarded against multiple inclusions.
- A header should hold definitions of macros, types and structures [1]
and declarations of functions (in prototyped form) and objects.
- A header sould be included when needed. Not less, not more.

------------------
[1] and the definitions of inline functions in C99 or more.


And some more general recommendations:

- The code should be organized into individual functionnal blocks with
a clear public interface.
- The code should be unit testable.
- The public interface is defined in a header file that belongs to the
functionnal block.

This is an important design guideline that helps to make solid,
efficient and reusable code.
 
D

Dan Pop

You have a good point about it having to compile. This particular header
problem has, in the first header, something like
typedef struct
{ int array[THIS_IS_DEFINED_IN_HEADER2]; } astruct;

and of course in the other header
#define THIS_IS_DEFINED_IN_HEADER2 5

This turns out to be the only dependant thing!
Normal practise, or poor coding?

It entirely depends on the application design. It is common practice
to have all the user-serviceable parts defined together in a single
header and all the other headers needing macros defined in that header
will have to include it. Ditto for special typedef's required by the
application.

IMHO, in a complex application with a well structured set of headers,
higher level headers will have to include lower level headers.

Of curse, I cannot make any comments WRT the design of your application.

Dan
 
D

Dan Pop

In said:
Heavy rules are raley useful. Better to act according to the situation.

I certainly hope that Emmanuel believes what he wrote above. (They're
called "strong rules", BTW.)
That said, here are some basics (call them rules if you want):

- A header should be guarded against multiple inclusions.
- A header should hold definitions of macros, types and structures [1]
and declarations of functions (in prototyped form) and objects.
- A header sould be included when needed. Not less, not more.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Doesn't this rule render the first one superfluous? ;-)

Dan
 
A

Arthur J. O'Dwyer

If you write a header file "header.h", then it must be written in such a
way that the single line source file

#include "header.h"

compiles without errors. That means header.h needs to include everything
that is necessary to make this work, but not more.

(Furthermore, it must be written in such a way that the /two-line/
source file

#include "header.h"
#include "header.h"

compiles without errors. That means header.h needs to include header
guards in the proper places.)
Note that a function can have arguments or return values of type "struct
xxx *" without having the declaration of struct xxx around; this feature
of C often makes it unnecessary to include header files within header
files.

I wouldn't consider that good practice, though. If "header.h"
uses anything declared in "foo.h", then "header.h" ought to #include
"foo.h" on general principles, so that the maintainer can see the
dependency --- even if the compiler might not care. After all, you
certainly wouldn't want

==foo.h==

struct Foo {
int i;
};

==header.h==

struct Foo *hello(void);

==bar.h==

struct Foo {
int i[1024];
};

==myprog.c==

#include "bar.h"
#include "header.h"

when the implementation of 'hello()' was expecting to return a
pointer to the type defined in "foo.h"! Better to include all
dependencies, and shake out the bugs early.

-Arthur
 
A

Alan Balmer

If you write a header file "header.h", then it must be written in such a
way that the single line source file

#include "header.h"
Agreed.

compiles without errors. That means header.h needs to include everything
that is necessary to make this work, but not more.

Note that a function can have arguments or return values of type "struct
xxx *" without having the declaration of struct xxx around; this feature
of C often makes it unnecessary to include header files within header
files.

Unnecessary, perhaps, but highly recommended nonetheless. There's no
good reason not to include the headers, and they should be there for
the benefit of the reader and so that the compiler can check the usage
of the function.
 
K

Keith Thompson

Arthur J. O'Dwyer said:
(Furthermore, it must be written in such a way that the /two-line/
source file

#include "header.h"
#include "header.h"

compiles without errors. That means header.h needs to include header
guards in the proper places.)

For certain values of "must". The #include directive just (in effect)
dumps the contents of the named header or file into your source at the
specified place. The language imposes few requirements on the content
of the header or the manner in which it's included, as long as the
final result is legal C. If "header.c" contains the line

i++;

then obviously the placement and number of any #include directives
will be significant, and the compiler is unlikely to complain.

But of course that kind of thing is horrendously bad style and is
shunned by all right-thinking programmers.

Which is a long-winded way of saying that I agree entirely, except
that I would have written "should" rather than "must". The meta-point
is that it's a matter of style (which of course doesn't make it
unimportant).
 
E

E. Robert Tisdale

John said:
What does the group think

"Group think" is an intellectual disease.
of the practise of including one header file from inside another?

It is essential.
I have some legacy code where this has been done,
and it creates a dependency on a module (collection of files)
which are not required, except for one header file's contents.

I'd say 'No,
header files should be included in the C source, not in another header',
but I've always come across strong arguments for the latter.

What do you think, and what is accepted practice?

Header files are files include'd by the C preprocessor
at the *head* of a C source file or another header file.
Files included elsewhere in the body of a source file
are not technically header files.

Header files are usually used to introduce *module interfaces*
into source programs. Such header files should be both

1. self-sufficient and
2. idempotent.

Self-sufficient means that the header file should include
all of the header files that it needs to compile properly.
Idempotent means that the content is protected by so-called
*guard macros"

#ifndef GUARD_FILE_H
#define GUARD_FILE_H 1
// contents
#endif//GUARD_FILE_H

that prevent the C preprocessor
from including the contents more than once.

Remember that an *interface* has no substance itself.
It contains function declarations, macro and type definitions
but nothing that would compel the compiler to emit code by itself.
Header files that effect module interfaces should *not* include
[global] function definitions!
This means that including unused interfaces should be *harmless* --
*no* dependencies should be created.
 
K

kal

That said, here are some basics (call them rules if you want):

- A header should be guarded against multiple inclusions.
- A header should hold definitions of macros, types and structures [1]
and declarations of functions (in prototyped form) and objects.
- A header sould be included when needed. Not less, not more.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Doesn't this rule render the first one superfluous? ;-)

No.
 
P

pete

kal said:
That said, here are some basics (call them rules if you want):

- A header should be guarded against multiple inclusions.
- A header should hold definitions of macros, types and structures [1]
and declarations of functions (in prototyped form) and objects.
- A header sould be included when needed. Not less, not more.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Doesn't this rule render the first one superfluous? ;-)

No.

If the main file #includes header file a.h,
which #includes header file b.h, which #includes header file c.h,
which has a FILE type parameter in a function prototype,
and which also #includes stdio.h, then I may be inclined,
when using a function like printf in the main file,
to also #include stdio.h in the main file,
even though it isn't needed there.

The reason being because I may want to be able to change
a.c and a.h, without changing the #includes in the main file.

It would depend on whether or not the features in a.c, a.h, b.c, b.h
and c.c, which required the inclusion of stdio.h,
were fundamental to the main file.
 
D

Dan Pop

In said:
[email protected] (Dan Pop) wrote in message news: said:
That said, here are some basics (call them rules if you want):

- A header should be guarded against multiple inclusions.
- A header should hold definitions of macros, types and structures [1]
and declarations of functions (in prototyped form) and objects.
- A header sould be included when needed. Not less, not more.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Doesn't this rule render the first one superfluous? ;-)

No.

Why? With few exceptions, no header *needs* to be included twice. And
these exceptions, obviously, don't have guards against multiple inclusion.

Dan
 
J

John Smith

John Smith said:
Hi all

What does the group think of the practise of including one header file from
inside another?

I have some legacy code where this has been done, and it creates a
dependency on a module (collection of files) which are not required, except
for one header file's contents.

I'd say 'No, header files should be included in the C source, not in another
header', but I've always come across strong arguments for the latter.

What do you think, and what is accepted practise?

Thanks
JS

What is this obsession with replying 'Don't forget the inclusion guard'???
It's old hat. My secnario has this in place.

My problem is one module is creating a dependancy on another module only
because the first module wants to use one single #define in the second
module.

The application is a large one, backed up by an overly sophisticated build
system, which would mean if I want to pick up module 2, I pick up all of it:
it all gets compiled. (And yes, I know: it won't get linked in!).

So the question is: is it normal practise to create intermodule dependancies
for trivial reasons?
 
A

Arthur J. O'Dwyer

John Smith said:
What does the group think of the practise of including one header file
from inside another?

I have some legacy code where this has been done [...]
What is this obsession with replying 'Don't forget the inclusion guard'???
It's old hat. My secnario has this in place.

Good. Many scenarios don't; or almost as bad, have incorrect header
guards, something like this picture. (A slightly interesting puzzle
is to count the number of mistakes in this header!)

#ifndef _MYHEADER_H
#define _MYHEADER_H

#ifdef __CPLUSPLUS__
extern 'C' {
#endif

#ifndef _STDIO_H
#include <stdio.h>
#endif

void foo(size_t bar);

#ifdef __CPLUSPLUS__
}
#endif
#endif

My problem is one module is creating a dependancy on another module only
because the first module wants to use one single #define in the second
module.

Well, if you use a macro that's #defined in another module, that would
be a dependency, yes. I think we all assumed that was clear.
The application is a large one, backed up by an overly sophisticated build
system, which would mean if I want to pick up module 2, I pick up all of it:
it all gets compiled. (And yes, I know: it won't get linked in!).

I would guess that very few people on this newsgroup have any experience
with your "overly sophisticated build system." Plain vanilla 'make' is
smart enough for many projects. And if a dependency on a /header file/
is causing any noticeable increase in compile time, I would say that your
build system has a design flaw.
So the question is: is it normal practise to create intermodule
dependancies for trivial reasons?

What counts as "trivial"? Most of my /programs/ are written for trivial
reasons (ranging from "because I want it" to "because I get paid to do it"
to "because I'm bored"). It sounds like you think this dependency is a
bad idea. Can you remove it without causing other bad side effects
(unmaintainability, making the chief programmer jealous, breaking the
build tool)? If so, why don't you just go ahead and /do/ it?

Ask a vague question, get a vague answer.

-Arthur,
about seven
 
M

Michael Mair

Hi John,

What is this obsession with replying 'Don't forget the inclusion guard'???
It's old hat. My secnario has this in place.

Right. Not everyone told you this but you got answers to your question
as well.
The reason you get the "old hat" is that your question is vague enough
that we cannot be sure whether you are aware of the safe include
mechanism and the errors forgetting it can cause.

My problem is one module is creating a dependancy on another module only
because the first module wants to use one single #define in the second
module.

Yes. You got answers to that. I gave one, people with more clue gave you
other answers.

The application is a large one, backed up by an overly sophisticated build
system, which would mean if I want to pick up module 2, I pick up all of it:
it all gets compiled. (And yes, I know: it won't get linked in!).

So the question is: is it normal practise to create intermodule dependancies
for trivial reasons?

Try to ask clearer questions, please. "Trivial" is not clear in this
context. If the two settings I described are trivial, then: yes, if
one is not: no.

Hint: Filter out the static (that is: the inclusion guard stuff),
have a look at the remaining answers, try to come up with smart
questions based on these answers. Most of us certainly do not want to
frustrate you (having better things to do with their time).
Please try not to frustrate us in turn :)


Cheers,
Michael
 
J

John Smith

Michael Mair said:
Hi John,



Right. Not everyone told you this but you got answers to your question
as well.
The reason you get the "old hat" is that your question is vague enough
that we cannot be sure whether you are aware of the safe include
mechanism and the errors forgetting it can cause.



Yes. You got answers to that. I gave one, people with more clue gave you
other answers.



Try to ask clearer questions, please. "Trivial" is not clear in this
context. If the two settings I described are trivial, then: yes, if
one is not: no.

Hint: Filter out the static (that is: the inclusion guard stuff),
have a look at the remaining answers, try to come up with smart
questions based on these answers. Most of us certainly do not want to
frustrate you (having better things to do with their time).
Please try not to frustrate us in turn :)


Cheers,
Michael


Sorry if I have frustrated you all, it certainly wasn't my intention.

Thanks for all the replies. I'll figure something out of it all, I'm sure.

JS
 
J

Jack Klein

What is this obsession with replying 'Don't forget the inclusion guard'???
It's old hat. My secnario has this in place.

My problem is one module is creating a dependancy on another module only
because the first module wants to use one single #define in the second
module.

The application is a large one, backed up by an overly sophisticated build
system, which would mean if I want to pick up module 2, I pick up all of it:
it all gets compiled. (And yes, I know: it won't get linked in!).

So the question is: is it normal practise to create intermodule dependancies
for trivial reasons?

In my opinion, a source file containing two single lines must compile
without diagnostics, or with only a diagnostic concerning the failure
of the translation unit to contain any external declarations:

#include "required_project_header.h"
#include "header_in_question.h"

....where "required_project_header.h" is just that, required to be the
first header included in every C source file in the project. It in
turn includes at least <stdint.h> and <stddef.h>, plus generally some
project-specific headers with universally used typedef's and macros.

In setting up the rules for our latest large C embedded project, I
tried to eliminate some of the more obvious disadvantages of earlier
project structures. The biggest of these was "header dependency
hell".

In earlier projects, functions and data types that provided interfaces
between various modules of the program were all placed in a single
header for each module, named xxx_api.h for module xxx.

The problem is that xxx_api.h almost always needed to include some
type defined by a different module in some structure of its own, or
accept or return one (or a pointer to one) in a function call.

So xxx_api.h required the inclusion of yyy_api.h, which in turn needed
something from zzz_api.h, and in the end way too many files ended up
including most or all of the API headers.

The obvious solution, which has reduced these dependencies greatly, is
to require two headers for things exported by each module:

xxx_api_types.h
xxx_api_calls.h

The latter, of course, must include the former. A few simple rules:

1. C source files may only include *_calls.h files, and never any
*_types.h, other than that belonging to its own module.

2. *.api_calls.h files must include their own api_types.h file, and
may include other *api_types.h files, but may not include any other
api_calls.h files.

This has cut the header coupling down significantly.

If you are working with legacy code, and can't completely reorganize
the code base, consider moving the one dependency to a header file of
its own:

some_header_name.h:

#ifndef THIS_IS_DEFINED_IN_HEADER2
#define THIS_IS_DEFINED_IN_HEADER2 5
#endif

Include this header in the big include file in place of the
definition, and include it in other places that only needed this
symbol from the big include file.

This is the sort of thing that is a good candidate for inclusion in
"required_project_header.h".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top