Cmath VS Math.H (And Similar C-Prefixed VS .H Extension Headers)

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.

is math.h for C or C++?

<math.h> is a header specified in the C standard. Its usage is supported in C++, but formally deprecated (which means, approximately, slated for potential removal from a future standard) by all C++ standards. I would suggest it is unlikely to be removed from a future C++ standard, for as long as backward compatibility to C is considered important or desirable.

<cmath> is a header specified in the C++ standard. It provides essentially the same functionality as in C's <math.h>, except that names (other than a couple of macros) reside in namespace std.

A similar story goes for <stdio.h> (C) and <cstdio> (C++), except that usage of stream I/O (e.g. <iostream>) is encouraged in C++.

Standard C++ headers never have a .hpp extension. That naming convention for headers is a convention encouraged by some, but is not formally required.

What is loaded into standard namespace?

C++ standard library includes most of the C library (there are some hazy details around optional parts of the C library).

Since C has no concept of namespacing, everything included from the C library will be in the global namespace. Since <math.h> is a C header, its functions are put into global namespace.

Everything included from the C++ standard library will be in the std:: namespace, like std::ifstream when you included <fstream> header.

Where it gets fun, are aliases. As an example, <math.h> can also be included as <cmath>. The idea behind this was that you select whether you want the C symbols in global namespace (including <math.h>) or in the std:: namespace (including <cmath>), but this didn't work out and generally if you include the C++ version of the header (ie <cmath>), you will get both.

Generally, if a header can either be included via <foo.h> or via <cfoo>, its a C header. C++ standard library headers do not have these aliases (except when you have to deal with non-standard things like iostream.h that apparently still exist on some platforms).

are C functions declared in c____ headers guaranteed to be in the global namespace as well as std?

Here's a nice synopsis of the situation (with some reality vs. what the standard says) from Stephan T. Lavavej of the MSVC team (http://blogs.msdn.com/vcblog/archive/2008/08/28/the-mallocator.aspx#8904359):

> also, <cstddef>, <cstdlib>, and std::size_t etc should be used!

I used to be very careful about that. C++98 had a splendid dream wherein <cfoo> would declare everything within namespace std, and <foo.h> would include <cfoo> and then drag everything into the global namespace with using-declarations. (This is D.5 [depr.c.headers].)

This was ignored by lots of implementers (some of which had very little control over the C Standard Library headers). So, C++0x has been changed to match reality. As of the N2723 Working Paper, http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2723.pdf , now <cfoo> is guaranteed to declare everything within namespace std, and may or may not declare things within the global namespace. <foo.h> is the opposite: it is guaranteed to declare everything within the global namespace, and may or may not declare things within namespace std.

In reality and in C++0x, including <cfoo> is no safeguard against everything getting declared in the global namespace anyways. That's why I'm ceasing to bother with <cfoo>.

This was Library Issue 456, http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#456 .

(C++0x still deprecates the <foo.h> headers from the C Standard Library, which is hilarious.)

I've never been fond of the <cfoo> headers myself, and found that I've always use <foo.h>. Now I feel like I can stop being anxious about my lack of C++ 'purity' in that regard.

Scope of C libraries in C++ - X.h vs cX

Stephan T. Lavavej, a member of the MSVC team, addresses the reality of this situation (and some of the refinements to the standard) in this comment on one of his blog postings (http://blogs.msdn.com/vcblog/archive/2008/08/28/the-mallocator.aspx#8904359):

> also, <cstddef>, <cstdlib>, and std::size_t etc should be used!

I used to be very careful about that. C++98 had a splendid dream wherein <cfoo> would declare everything within namespace std, and <foo.h> would include <cfoo> and then drag everything into the global namespace with using-declarations. (This is D.5 [depr.c.headers].)

This was ignored by lots of implementers (some of which had very little control over the C Standard Library headers). So, C++0x has been changed to match reality. As of the N2723 Working Paper, http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2723.pdf , now <cfoo> is guaranteed to declare everything within namespace std, and may or may not declare things within the global namespace. <foo.h> is the opposite: it is guaranteed to declare everything within the global namespace, and may or may not declare things within namespace std.

In reality and in C++0x, including <cfoo> is no safeguard against everything getting declared in the global namespace anyways. That's why I'm ceasing to bother with <cfoo>.

This was Library Issue 456, http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#456 .

(C++0x still deprecates the <foo.h> headers from the C Standard Library, which is hilarious.)

I'm in 100% agreement with Lavavej, except I never tried to be very careful about using the <cfoo> style headers even when I first started using C++ - the standard C ones were just too ingrained - and there was never any real world problem using them (and apparently there was never any real world benefit to using the <cfoo> style headers).

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++.

G++ math.h problem

I found a solution!

I downloaded and installed MinGW instead, and that works fine. I have all the function prototypes for extra stuff like gettimeofday(), and all the regular suff like tanf() is still working fine.

ps: visual studio even has a button for "Use Output Window" where it nicely dumps any errors that are generated by "arm-none-linux-gnueabi-g++"

Why is there a c prefix in the C++ version of C libs?

EDIT: Okay, we have some people who maybe didn't read the question carefully enough, or made assumptions on what the question meant or how answers were to be interpreted.

I'm answering the below question here:

but what was the reason to choose to use the "c" prefix?


To emphasize that it's originally from the C language, I presume.

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>.



Related Topics



Leave a reply



Submit