Should I Include <Xxxx.H> or <Cxxxx> in C++ Programs

Should I include xxxx.h or cxxxx in C++ programs?

Consider the following programs:

Sample 1:

#include<stdio.h>

int main()
{
printf("Hello World");
return 0;
}

Sample 2:

#include<cstdio>

int main()
{
printf("Hello World");
return 0;
}

Both work as expected. So which usage is more appropriate?
The answer is: Neither! Surprised? Read on.

The C++ Standard library provides all standard C headers for compatibility reason, while C++ as a language also provides all the equivalent headers. As a convention,

  • No C++ standard library headers(apart from ones include for C compatibility) have any file extensions, and
  • All C++ equivalent of C headers begin with cxxxxx.

The C++ Standard mentions this under Annex D (normative) Compatibility features:

Standard Citation

§2 mentions the important distinguishing point. This rule applied to the examples above means:

  • Including cstdio imports the symbol names in the std namespace and possibly in the Global namespace.
  • Including stdio.h imports the symbol names in the Global namespace and possibly in the std namespace.

Let us apply this rule to our sample codes and measure the pros and cons:

Sample 1:
This brings all the symbols from stdio.h in the global namespace. Advantage is that you can use the symbols without any qualification since they are imported in the global namespace. Downside is that you end up polluting the global namespace with many symbol names that you will probably never use. This might lead to symbol name collision. In C++ always consider the global namespace as a minefield and avoid it as much as possible.

Sample 2:
This is a very bad practice because there is no guarantee that the implementation will put the symbols in global namespace, the standard simply does not demand to do so. We are simply relying on the behavior of one particular compiler implementation. We cannot and should not assume that all compilers will do so. So strictly speaking the program is not standard approved and this usage is not portable across all implementations.

So what is the correct usage?

The correct usage is to use cstdio and fully qualify the symbol names or else bring them in scope with using declarations. This guarantees all symbols we use are present in std namespace and we are not polluting the global namespace. Example of correct usage:

Sample 3:

#include<cstdio>

using std::printf;

int main()
{
printf("Hello World");
return 0;
}

Note that the directive using namespace std;, especially in a header, is not a good option and you should always use using declarations.

Note that we consider stdio.h vs. cstdio here just a sample use case, in practice it applies to all most cxxxx and xxxx.h headers, except a few like <math.h> and <cmath>.

Is it better to include cassert or assert.h ?

The contents of <cassert> are the same as the C standard library header <assert.h>, except that a macro named static_assert is not defined.1

Prefer <cassert>.

All of the <xxx.h> C headers (including <assert.h>) are deprecated:

D.5 C standard library headers [depr.c.headers]

Update regarding the static_assert macro from C

In D.5 [depr.c.headers], the C++ standard refers to the <xxx.h> headers as "the C headers:

1 For compatibility with the C standard library, the C++ standard library provides the C headers shown in Table 141.

In C++14, the specification referenced C99 (ISO/IEC 9899:1999). C99 did not define the macro static_assert (in any header). C++14 had this to say about <cassert> in 19.3 [assertions]:

2 The contents are the same as the Standard C library header <assert.h>.

C++17 references C11 (SO/IEC 9899:2011) which does define static_assert in <assert.h>, and has this to say about <cassert> in 22.3.1 [cassert.syn]:

1 The contents are the same as the C standard library header <assert.h>, except that a macro named static_assert is not defined.

Both C++14 and C++17 define <assert.h> only by reference to their respective C specifications, and also by this:

See also: ISO C 7.2.

(which is the C section that specifies <assert.h>)

The way I read this, techincally <assert.h>, when compiled with a C++17 compiler, actually does define a macro named static_assert. However doing so would be pointless, and I can't imagine that any implementation actually bothers to do so.

In any event, I stand by my recommendation above:

Prefer <cassert>.

It's just the C++ way to do things. And at least in C++98/03/11/14/17, it avoids depending on deprecated functionality. Who knows what C++20 will bring. But C++20 definitely will not deprecate <cassert>.


1 22.3.1 Header synopsis [cassert.syn]

2 Link to the C++11 specification.

3 Link to the C++17 specification.

Why use cheader instead of header.h ?

How does that code snippet compiles then (g++ 4.7.3)?

Because 17.6.1.2/4 of the C++11 Standard specifies:

[...] It is
unspecified whether these names are first declared within the global namespace scope and are then injected
into namespace std by explicit using-declarations (7.3.3).

Therefore, implementations are allowed to define those entities in the global namespace.

Why should one include then (instead of ) if standard C functions will be in the global namespace anyway?

First of all, as a matter of good style. Including <stdio.h> gives you the certainty that all the entities are defined in the global namespace, while including <cstdio> gives you the certainty that those entities are where you want (in the std namespace), with the possible (but not certain) unwanted drawback that those names may appear in the global namespace too.

what should I do to get some of these functions out of the global namespace (while using c++ headers at the same time)?

Unfortunately, you cannot get an entity out of the namespace it lives in. But what you can do (apart from cursing at your implementation) is to avoid using Standard C functions altogether, and prefer using functions from the C++ Standard Library. Those are guaranteed to live in the std namespace.

So for instance, if you have to perform low-level memory management, use the new operator instead of malloc. Also, mind the emphasis on "have to": most of the time, you should use RAII wrappers such as smart pointers or standard containers to avoid having to cope with low-level memory management, new, and delete at all.

#include cmath vs #include math.h in a C++ program

Prefer to include the <c ...> headers. They are C++ standard library headers. The <... .h> headers are headers defined by the C standard library:

The C++ standard library also makes available the facilities of the C standard library, suitably adjusted to ensure static type safety.

The C++ headers, for the most part, have content identical to the corresponding C library headers except that the names are all defined in the std namespace.

Except as noted in Clauses 18 through 30 and Annex D, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in the C standard library (1.2) or the C Unicode TR, as appropriate, as if by inclusion. In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations

Disadvantages of a std.h file that brings in all std headers?

Including unnecessary header files will increase compile times.

Math interface vs cMath in C++

In the C++ standard, the math library functions are defined in two headers:

<cmath>

contains them in the namespace std (e.g. std::sin), while

<math.h>

contains them in the global namespace (so just sin).

There are further differences between the two: while <math.h> contains all the C math functions with distinct names for distinct types, such as

double sin(double);
float sinf(float);
long double sinl(long double);

etc., <cmath> contains overloaded functions such as

namespace std {
double sin(double);
float sin(float);
long double sin(long double);
}

etc. (C++ libraries might additionally export sinf from <cmath>, but you can't rely on this in a portable program.)

Finally, the fabs, fabsf and fabsl functions from the C standard library have become overloads of std::abs in <cmath>.

Though both headers are in the standard, you should really prefer <cmath>, as <math.h> is only there for backward compatibility with pre-standard C++ and C.

There's no such thing as <cmath.h> in standard C++.

cmath vs math.h (And similar c-prefixed vs .h extension headers)

I've seen some information about differences between things like iostream vs iostream.h.

[iostream.h] is not a standard header.

it is not an example of the issue you're raising.

[cmath] defines symbols in the std namespace, and may also define symbols in the global namespace. [math.h] defines symbols in the global namespace, and may also define symbols in the std namespace. if you include the former and use an unqualified symbol, it may compile with one compiler but not with another. therefore it's a good idea to use [math.h]. and in general, for such header pairs, to use the [.h] version.

c++98 provided a formal guarantee of the cxxx header not polluting the global namespace. maybe that was why they were defined. however, that was a bit harder to implement than polluting ones, so in practice no standard library implementation that i know of followed the standard in this respect, and so it was finally changed to reflect reality in c++11.

What am i doing wrong in string.h function usage?

First, strupr is not part of the standard C library nor the standard C++ library. So there is no standard header that is required to declare it.

That said, it started out as a Microsoft thing, and was, indeed, declared in <string.h>. See this question for more discussion.

So, unless your compiler has it as an extension, it won't exist. That's what the error message is telling you.

Even if it does exist, you can't use it the way that the code in the question tries to do. The problem is that it modifies the contents of its argument, so you can't pass a const char* to it. That's what this code does:

strupr("hello world");

"hello world" is a string literal, and in the olden days its type was char[12], that is, formally, it looked like a modifiable string. But in fact, it was up to the compiler to decide whether string literals were modifiable, so with some compilers it was okay and with others it wasn't. When it wasn't, it would be because the compiler put string literals in read-only memory, so attempting to modify the literal would produce a runtime error.

In C++, the type of "hello world" is const char[12], that is, the characters in the string are not modifiable. So calling strupr("hello world") is ill-formed, and the compiler should issue a diagnostic.

To make it work, if your compiler provides this function, you have to call it on a modifiable string:

char str[] = "hello world";
strupr(str);

str is a modifiable array of char that holds a copy of the text in its initializer, in this case, "hello world". That string can be modified, so strupr can do its job.

Should I include stddef.h or cstddef for size_t

I prefer #include <stddef.h>.

Some of the names in the C headers are allowed to be macros, but the set differs from the C rules. In C, EXIT_FAILURE, isdigit(), getc() a.o. are macros. Do you know which ones are macros in C++?

Secondly, only a couple standard C headers are required to have the <cfoo> header, Posix headers are not. Do you know which headers are standard and which ones are provided by your compiler only?

Thirdly, when using headers from a third-party C library, you will end up with #include <stddef.h>, and I prefer not to mix <stddef.h> and <cstddef>.

Fourthly, the current draft for the new C++ standard says that <cstdlib> is allowed to dump the symbols into the global namespace (because apparently many compilers already do so nowadays), so using #include <cstdlib> is not a guarantee that the global namespace will be unpolluted in the future. So I would advice that when writing portable code, you should assume the global namespace will be affected (even though it is not allowed now). As only a few experts seem to know this (see the discussion in the comments here), it is better to use <stddef.h> as even a beginning C++ programmer will understand that it pollutes the global namespace.



Related Topics



Leave a reply



Submit