Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

<cstdint> vs <stdint.h>

What is the difference between stdint.h and cstdint?

Both of them are available in MSVC (Visual Studio 2010) and gcc-4.5.1. Also both define the intX_t/uintX_t types (where X is the size in bytes of the type).

  • If the rationale in both headers is the same (portable types), what decisions I must take to decide on one or the other?

The stdint.h defines each type without any namespace, the cstdint types lies in the std namespace.

  • Is there any reason to include or to not include the defined types into the std namespace? What is different between the two headers?

cstdint has no file extension and uses the c prefix, stdint.h uses the .h extension.

  • What are the naming conventions for this headers? the c prefix indicates that this is a C library? there's a reason for the lack of file extension in cstdint?
like image 912
PaperBirdMaster Avatar asked Nov 30 '12 09:11

PaperBirdMaster


2 Answers

The original intention in C++98 was that you should use <cstdint> in C++, to avoid polluting the global namespace (well, not <cstdint> in particular, that's only added in C++11, but the <c*> headers in general).

However, implementations persisted in putting the symbols into the global namespace anyway, and C++11 ratified this practice[*]. So, you basically have three options:

  • Use <cstdint> and either fully qualify each integer type you use or else bring it into scope with using std::int32_t; etc (annoying because verbose, but it's the right way to do it just like for any other symbol in the C++ standard library)
  • Use <stdint.h> (slightly bad because deprecated)
  • Use <cstdint> and assume your implementation will put the symbols in the global namespace (very bad because not guaranteed).

In practice I suspect that an annoying large amount of code uses the last option, simply because it's easy to do by accident on an implementation where <cstdint> puts the symbols in the global namespace. You should try to use the first. The second has one virtue, that it is guaranteed to put stuff in the global namespace instead of only maybe doing it. I don't think that's particularly useful, but it might save some typing if that's your priority.

There's a fourth option, #include <cstdint> followed by using namespace std; which is sometimes useful but there are places that you shouldn't put the using namespace std;. Different people will have different ideas where those places are, but "at top level in a header file" is worse than "at top level in a cpp file", which is worse than "in a limited scope". Some people never write using namespace std; at all.

[*] That means C++ standard headers are permitted to put stuff in the global namespace but not required to. So you have to avoid colliding with those symbols, but you can't actually use them because they might not be there. Basically, the global namespace in C++ is a minefield, try to avoid it. One might argue that the committee has ratified a practice by implementations that is nearly as harmful as sticking using namespace std; at top level in a header file -- the difference being that the implementations only do it for symbols in the C standard library, whereas using namespace std; does it for C++-only symbols too. There's a section in the C standard that lists names reserved for future additions to the standard. It's not a completely stupid idea to treat those names as reserved in the C++ global namespace too, but it's not essential.

like image 77
Steve Jessop Avatar answered Nov 03 '22 08:11

Steve Jessop


Including cstdint imports the symbol names in std namespace and possibly in Global namespace.
Including stdint.h imports the symbol names in Global namespace and possibly in std namespace.

Features of C standard Library are also provided in the C++ Standard library and as a general naming convention they are pre-pended by an c to the corresponding names in C standard library.

In C++, You should be using:

#include <cstdint>

and fully qualify the symbol names you use with std::
while in C, You should use:

#include <stdint.h>

Annex D (normative) Compatibility features [depr] states:

D.6 C standard library headers

1 For compatibility with the C standard library and the C Unicode TR, the C++ standard library provides the 25 C headers, as shown in Table 151.

Which include:

<assert.h> <float.h> <math.h> <stddef.h> <tgmath.h> <complex.h> <inttypes.h> <setjmp.h> <stdio.h> <time.h> <ctype.h> <iso646.h> <signal.h> <stdint.h> <uchar.h> <errno.h> <limits.h> <stdarg.h> <stdlib.h> <wchar.h> <fenv.h> <locale.h> <stdbool.h> <string.h> <wctype.h>

And further,

2 Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).

3 [ Example: The header <cstdlib> assuredly provides its declarations and definitions within the namespace std. It may also provide these names within the global namespace. The header <stdlib.h> assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It may also provide these names within the namespace std. —end example ]

like image 45
Alok Save Avatar answered Nov 03 '22 09:11

Alok Save