<cstdint> vs <stdint.h>
Asked Answered
M

3

116

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 of the type in bits).

  • 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?
Modesta answered 30/11, 2012 at 9:58 Comment(2)
OS X 10.8 lacks <cstdint>. Here's the error I receive: ./misc.h:7:10: fatal error: 'cstdint' file not found.Doeskin
Related: When using C headers in C++, should we use functions from std:: or the global namespace?Cookshop
J
148

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.

Joceline answered 30/11, 2012 at 10:8 Comment(4)
The only unanswered question that remains is about the naming conventions of the header files, do you know about this topic?Modesta
@PaperBirdMaster: C++ standard library headers don't have file extensions: <iostream>, <vector>, <cstdlib>, apart from the ones included for C compatibility: <stdint.h>, <stdlib.h>. And yes, the initial c indicates that <cstdlib> is C++'s equivalent of the C standard header <stdlib.h>, rather than being wholly new to C++ like <vector> is. There's a C++ header <complex>, so we'll just have to hope that no future version of C introduces a standard header <omplex.h>.Joceline
@SteveJessop Erm, C99?Chaunce
@JL2210 notice that he said <omplex.h>, not <complex.h>. If C added <omplex.h>, the C++ equivalent would be <complex>.Kissinger
H
19

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 ]

Haugh answered 30/11, 2012 at 10:3 Comment(0)
O
0
  1. cstdint is C++11 header, stdint.h is C99 header (C and C++ are different languages!)

  2. MSVC 2008 contains neither stdint.h nor cstdint.

  3. Implementations of cstdint are mostly simply #include <stdint.h> with some namespace/language fixes.

Ovenware answered 30/11, 2012 at 10:3 Comment(5)
3. is wrong. cstdint needs to hoist the implementations into the namespace std.Patricide
1. is wrong as well, stdint.h is defined as a part of the C++ library in the normative Annex D of the C++ standard.Buroker
@chill, could you please provide link to Annex D? Here en.cppreference.com/w/cpp/types/integer stated that is C++11 header.Ovenware
@hate-engine, I suggest you look it up in your copy of the C++ standard. That cppreference page does not mention stdint.h. There's no argument that cstdint is a C++ header.Buroker
No part of 1. is false, it's just that taken together it looks as though you're saying stdint.h is not part of C++11. In fact it is required by C++11. You could say, "int is in C++11; long is in C99; C and C++ are different languages!", and no part of that would be false either. My example is even more misleading, though, since C++11 refers in part to C99 to define the contents of both stdint.h and cstdint, but doesn't refer to C to define int.Joceline

© 2022 - 2024 — McMap. All rights reserved.