Why Do Some Includes Need the .H and Others Not

Why do some includes need the .h and others not?

All standard C++ headers don't want the .h in the end. I read somewhere that the concept is that they don't need to be actual files, even if I never saw an implementation do it in another manner edit: actually the compiler intrinsics should work considering the headers included but not actually including them as files; see @Yttrill's comment.

For the stdio.h thing, in a C++ application you shouldn't include <stdio.h>, but you should instead include <cstdio>. In general, you shouldn't include the "normal" C headers, but their C++-ized counterparts, which haven't got the .h in the end, have a c in front and put all the symbols defined in them in the std namespace. So, <math.h> becomes <cmath>, <stdlib.h> becomes <cstdlib>, and so on.

In general, you should use the C++-ized versions of C headers both to avoid to pollute the global namespace (assuming you're not one of those guys who put using namespace std; everywhere) and to benefit of some C++ improvements to the standard C headers (e.g. added overloading to some math functions).



In general, the implementation of this whole thing is simply done by having such files without extension in the directory in which the compiler looks for the header files. In my g++ 4.4 installation, for example, you have:

matteo@teoubuntu:/usr/include/c++/4.4$ ls
algorithm cstdarg functional sstream
array cstdatomic initializer_list stack
backward cstdbool iomanip stdatomic.h
bits cstddef ios stdexcept
bitset cstdint iosfwd streambuf
c++0x_warning.h cstdio iostream string
cassert cstdlib istream system_error
ccomplex cstring iterator tgmath.h
cctype ctgmath limits thread
cerrno ctime list tr1
cfenv cwchar locale tr1_impl
cfloat cwctype map tuple
chrono cxxabi-forced.h memory typeinfo
cinttypes cxxabi.h mutex type_traits
ciso646 debug new unordered_map
climits deque numeric unordered_set
clocale exception ostream utility
cmath exception_defines.h parallel valarray
complex exception_ptr.h queue vector
complex.h ext random x86_64-linux-gnu
condition_variable fenv.h ratio
csetjmp forward_list regex
csignal fstream set

The C++-ized C headers in theory could just be a

namespace std
{
#include <original_C_header.h>
};

but in general they are more complicated to deal with implementation-specific problems (especially regarding macros) and to add C++-related functionality (see e.g. the previous example of added overloads in <cmath>).



By the way, the C++ standard (§D.5) do not say that the <c***> headers should behave as if they included the <***.h> headers in a namespace std directive, but the opposite:

For compatibility with the Standard C library, the C++ Standard library provides the 18 C headers [...]
Each C header, whose name has the form name.h, behaves as if each name placed in the Standard library namespace by the corresponding cname header is also placed within the namespace scope of the name-space std and is followed by an explicit using-declaration (7.3.3)

Notice that such headers are considered deprecated (§C.2.1), so this is the main reason you shouldn't use them:

C.2.1 Modifications to headers
For compatibility with the Standard C library, the C++ Standard library provides the 18 C headers (D.5),
but their use is deprecated in C++.

C++ includes with and without .h

<string> is the C++ standard library string header file containing std::string and its friends. <string.h> is a different header, from the C standard library, which has functions for manipulating C strings (null-terminated strings) and other related functions.

The two are entirely different and unrelated. In C++ (as in C), a header file can have any extension. The C++ standard library headers have no extension; the C standard library headers have a .h extension. .hpp or .hxx are also common.

Any good reason for C++ header file to not include any other header files?

It seems whoever wrote that code misunderstood the common recommendation of reducing the number of included headers. It is usually recommended to remove unnecessary #include <> directives in the hope of accelerating compilation. Indeed, on large projects, it may accelerate compilation significantly by:

  1. reducing the number of header files the compiler needs to open to compile any given source file;
  2. reducing the number of source files that need to be recompiled after a header changes.

In general, people will recommend (its been on coding standards for all projects I've worked on) using forward declarations for classes unless the class defined in the concerned header is:

  1. used as a base class;
  2. used as a data member;
  3. has an incomplete official speciifcation (e.g. standard library containers are allowed to have extra template arguments as long as they have defaults, so it's non-standard to forward declare them).

In cases 1 and 2, the #include <> directive must appear before the class definition in all dependent source files and headers. Basically, it just moves the #include <> directive(s) from the header into each of its dependencies. It results in more code and does so with no benefit (e.g. compilation time etc. will be the same). For this reason, this recommendation is also accompanied by another entry in the coding standard: each header file should compile "stand alone" (e.g. included on the first line of a source file).

Difference between using #include<filename> and #include<filename.h> in C++

C++ only include-files not found in the C standard never used filename.h . Since the very first C++ Standard came out (1998) they have used filename for their own headers.

Files inherited by the C Standard became cfilename instead of filename.h. The C files inherited used like filename.h are deprecated, but still part of the C++ standard.

The difference is that names not defined as macros in C are found within namespace std:: in cfilename in C++, while names in filename.h are within the global namespace scope. So you will find ::size_t in stddef.h, and std::size_t in cstddef. Both are Standard C++, but use of ::size_t is deprecated (See Annex D of the C++ Standard).

Now those were the difference.

Why would you use `filename.h` ?

  • Compatibility with C compilers
  • Compatibility with very old C++ compilers

Why should you use `cfilename` ?

  • Names are within namespace std:: . No name-clashes anymore.
  • New C++ features (e.g. overloaded math functions for float, long)
  • C Compatibility Headers (filename.h) could disappear in future.

Why are .h files included in .cpp files and not vice versa?

This seems to be the right etiquette anyway.
It's not a matter of etiquette, but .cpp files are considered as translation units and handled as such by any decent compiler or build system.

The .h files contain all the declarations needed to be seen for use in other translation units.

The compiled .cpp files are stitched together in the final linking phase.

This way though, I'm not including the .cpp file anywhere, and currently my code is complaining about not finding the functions therein. What am I doing wrong?

You probably missed to get that last part of linking the generated object files right.


As for your edit:

You're showing a template declaration now, which is a more special case. The compiler needs to see the template definitions to get them instantiated correctly.

You can read more about the details here: Why can templates only be implemented in the header file?

#include in .h or .c / .cpp?

Put as much as you can in the .c and as little as possible in the .h. The includes in the .c are only included when that one file is compiled, but the includes for the .h have to be included by every file that uses it.

When is .h not needed to include a header file?

It's not needed for the header files defined by the C++ Standard, none of which have a .h extension. The C++ version of stdio.h is:

#include <cstdio>

which wraps stdio.h, placing the names in it in the C++ std namespace,
but you can still use all the C Standard header files in C++ code, if you wish.

Edit: The macro that places the names in the std namespace in the GCC version of cstdio is:

_GLIBCXX_BEGIN_NAMESPACE(std)

You can check that your own header does what it should do by trying to use something like:

std::printf( "hello" );

in your code.

Why is it discouraged to include features.h?

glibc guarantees that #defines of the documented feature selection macros (_POSIX_C_SOURCE, _XOPEN_SOURCE, _GNU_SOURCE, etc) will be honored as long as they take effect before the first inclusion of any public C library header. For instance

/* file header comment */
#define _XOPEN_SOURCE 700 // first non-comment line of the file
#include <unistd.h> // first #include in the file
// ... more code here ...

is guaranteed to make unistd.h declare things that are part of POSIX.1-2008 including XSI extensions.

The implementation of this guarantee involves features.h, but features.h is not a public C library header. Direct inclusion of features.h is not something you should ever need to do, and we (glibc devs) do not promise that this header will even continue to exist in the future. (For instance, a future release might merge it into bits/libc-header-start.h.)



Related Topics



Leave a reply



Submit