60

When writing C++ code is there any difference between:

#include <cstdlib>

and

#include <stdlib.h>

other than the former being mostly contained within the std:: namespace?

Is there any reason other than coding standards and style to use one over the other?

George Kagan
  • 5,913
  • 8
  • 46
  • 50
Free Wildebeest
  • 7,272
  • 8
  • 38
  • 42
  • Possible duplicate of [What's the main difference between stdlib.h and cstdlib in C++?](https://stackoverflow.com/questions/2847729/whats-the-main-difference-between-stdlib-h-and-cstdlib-in-c) – phuclv Sep 02 '17 at 15:55
  • Something none of the answers seem to have mentioned: in C++ the latter is **deprecated**. – Pharap Jun 24 '18 at 02:03
  • @Pharap Fixed it – klutt May 07 '19 at 14:01

3 Answers3

54

The first one is a C++ header and the second is a C header. Since the first uses a namespace, that would seem to be preferable.

Brendan Long
  • 53,280
  • 21
  • 146
  • 188
17

No, other than the namespace situation, they're essentially identical.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
11

Is there any reason other than coding standards and style to use one over the other?

Yes. The fact that stdlib.h is deprecated is a very good reason to not use it. It was actually deprecated in the very first standard that came 1998. Sure, it still existed in C++14, and possibly or even probably in C++17 (I don't have access to the C++17 standard) but since it is deprecated it is strong signal that you should not use it. Maybe the risk of removal isn't very high, but why even risk it while writing new code when it is so easy to avoid?

From C++14 standard:

These are deprecated features, where deprecated is defined as: Normative for the current edition of the Standard, but having been identified as a candidate for removal from future revisions.

...

You should have a pretty strong argument to use stdlib.h instead of cstdlib. Unless you can come up with one, use cstdlib.

Apart from that, you also have the practical matter that cstdlib is using a namespace, which is preferable in most cases.

klutt
  • 30,332
  • 17
  • 55
  • 95
  • 6
    That is also completely useless because it will never be removed anyway - interoperability with C requires this. –  May 07 '19 at 13:56
  • 1
  • 1
    @LightnessRacesinOrbit C headers will include `stdint.h` and will use types from a global namespace. Forcing people to ifdef everything for both languages is impractical.Compilers will ship it regardless of what standard says. Most code bases do not even care about both headers and `std::` before type names. –  May 07 '19 at 14:22
  • 1
    @StaceyGirl True, but most (maybe ALL) C headers are deprecated. – klutt May 07 '19 at 14:25
  • 1
    @StaceyGirl So you're not talking about interop, but about building the same code in both languages. Yes, in that case, all your C needs to be valid C++ and vice versa. However if you split your headers and source files properly and build your C source files as C then I can't see a problem? – Lightness Races in Orbit May 07 '19 at 14:27
  • @LightnessRacesinOrbit Headers shipped with C library need to contain a code that is valid in both languages. Putting `extern "C"` is relatively simple, but adding/omitting `std::` for each type is just PITA. Atomics already suffer from this. Most people don't even do this for C++ code (I mean using `std::size_t` vs `size_t`). –  May 07 '19 at 14:32
  • 1
    @StaceyGirl Why would you need to `#include ` in a header? Why do you have code other than declarations in such a header? – Lightness Races in Orbit May 07 '19 at 14:33
  • 1
    (Note that I'm mostly being picky about your rationale; I do agree that it would be better for everybody if these headers remained in place, and it seems like the working group does too!) – Lightness Races in Orbit May 07 '19 at 14:34
  • @LightnessRacesinOrbit Because types are used in declarations. You can says that all supported platforms will have 32-bit `int`, 64-bit `long long` etc. But at least things like `size_t` cannot be replaced with built-in types. I think the committee just want's to discourage people from using those headers by declaring them deprecated. Doesn't really work, sometimes I feel I am the only one that writes `std::size_t` and even I sometimes wonder why should I even bother. –  May 07 '19 at 14:38
  • @StaceyGirl You should use `stddef.h` (or `cstddef`) for `size_t` (or `std::size_t`) – Lightness Races in Orbit May 07 '19 at 14:42
  • @LightnessRacesinOrbit `uint32_t`, `uintptr_t` - whatever. `stddef.h` has the same problem as `stdint.h`. –  May 07 '19 at 14:45
  • 1
    @StaceyGirl I'd say `stddef.h` has the problem whereas `stdlib.h` (the header in question) doesn't! – Lightness Races in Orbit May 07 '19 at 14:46
  • @StaceyGirl "code" is uncountable (i.e. singular and plural), you cannot have "a code". Personally I always either qualify `std::` or use a function-local using directive in my C++ code. If the code bases you work with aren't doing that, inform the maintainers that they should be doing that. Also `` guarantees that (for example) `std::malloc` exists, but not that `::malloc` exists. `` has the reverse guarantee: it guarantess that `::malloc` exists, but not `std::malloc`. If `cstdlib` includes `::malloc` or `stdlib.h` includes `std::malloc`, that's pure coincidence. – Pharap May 07 '19 at 16:06
  • @Pharap It was about `stdlib.h` which should provide a definition for `size_t`. That header exists and will exist and will not be removed, regardless of its deprecation status. Many (if not most) project use types like `size_t` this way - without `std::`. For example basically anything published by Google. –  May 07 '19 at 16:30
  • @StaceyGirl What I said for `std::malloc` applies to `std::size_t` too. You can never be sure if or when deprecated features will be removed. C++17 removed quite a lot of things that I once would never have thought would be removed. For example, the keyword `register`, `std::auto_ptr`, `std::random_shuffle` and `throw(type)` (and later C++20 removed `throw()`). If Google has been using deprecated headers in their projects then that's their problem. That doesn't mean compilers won't still support removes features, but it means they won't be required to. – Pharap May 07 '19 at 17:12
  • 1
    @Pharap Wrong. Removing `stdlib.h` is not the same as removing `std::auto_ptr`. It still exists in C and is basically _required_ to be there to write libraries that work in both languages. I myself use `cstdxxx` when writing C++ and put `std::` everywhere, but it doesn't change the fact that you _can_ include `stdlib.h` and use `size_t` everywhere and it will be portable. What standard says/deprecates/removes is irrelevant. C99 has removed function calls without prototypes, but all compilers still allow it. –  May 07 '19 at 17:17
  • 1
    @StaceyGirl It is the same in that both decisions break backwards compatibility (and thus break existing code). C headers aren't required to be able to write libraries that work in both languages. It's perfectly possible to conditionally include `` instead and bring the names from `std::` into the global scope with a using directive. Aside from which, mixing C and C++ code should be kept to a minimum because not all valid C is valid C++ and [code behaviour can differ drastically](https://en.wikipedia.org/wiki/Compatibility_of_C_and_C). – Pharap May 07 '19 at 17:38
  • @StaceyGirl The standard is never irrelevant. It dictates what a compiler _must_ and _must not_ do to be compliant, and what it's _allowed_ to do whilst still remaining compliant. If compilers wish to include non-standard extras they are allowed, but programs that depend on that compiler-specific behaviour may not compile on other standard-compliant compilers, therefore it's in the best interest of all code (that needs to be portable) to adhere to the standard and not the behaviour of any particular compiler. – Pharap May 07 '19 at 17:41
  • @Pharap If standard doesn't guarantee something, it doesn't mean it is not allowed, only that standard doesn't bother supporting it. This has nothing to do with portability and many extensions (GCC ones) are more portable than equivalent "standard" constructs. In the end, standard is largely irrelevant, only working code does. That is why many compilers violate the standard and treat it as a feature, especially the C standard (as with proof of loop-termination). When paper and reality clash, reality wins. _Always_! –  May 07 '19 at 17:49
  • "If standard doesn't guarantee something, it doesn't mean it is not allowed" I already said that: "If compilers wish to include non-standard extras they are allowed, but programs that depend on that compiler-specific behaviour may not compile on other standard-compliant compilers". "many extensions (GCC ones) are more portable than equivalent "standard" constructs" this is _not_ the case. Just look at [the difference in packing](https://stackoverflow.com/q/1537964) between GCC and Visual C++. The standard is what governs the minimum guarantees of every C++ compiler. – Pharap May 07 '19 at 19:26
  • @StaceyGirl *"and many extensions (GCC ones) are more portable than equivalent "standard" constructs"* - I would really like to hear a motivation and an example of this. – klutt Feb 23 '22 at 11:24
  • @klutt There are more compiles that support GCC's `__attribute__((noreturn))` than compilers that support C11 `_Noreturn`. Plus it works for both C and C++. C23 must fix this with `[[noreturn]]`, but there are other things too. –  Feb 23 '22 at 11:35
  • @StaceyGirl Do these compilers claim to support C11? – klutt Feb 23 '22 at 11:39
  • @klutt How does it matter? Portability is about number of platforms your code can run on. More portable = more platforms. And even with C11 compilers, `__attribute__((noreturn))` is still more portable if you need to support both C and C++, until at least C23 becomes widely available. But even after that, there is no portable way to do atomics yet ( won't be available for Clang on Windows for example and it is still different from ), so GCC's `__atomic_*` builtin will be more portable for a while. –  Feb 23 '22 at 11:47
  • @StaceyGirl I just got the impression that you meant that it's common that compilers does not follow the standard they claim to do. – klutt Feb 23 '22 at 11:54
  • @klutt Well, I don't know a compiler that follows the standard to the word. Most violate it in at least few places (that includes GCC and Clang). –  Feb 23 '22 at 12:05
  • @StaceyGirl To be clearer, it sounded like you meant that the reason "equivalent standard constructs" aren't portable is that the compilers doesn't support what they claim to do. – klutt Feb 23 '22 at 12:07
  • @klutt I think my point was that "standard" and "portability" are orthogonal, but that is not how people think of them. As for compiler claims, MSVC is marketed as compiler with C++17 support, but it doesn't as it misses `std::aligned_alloc` at least. GCC/Clang violate some portions of C99, but seem to claim to support it. –  Feb 23 '22 at 12:12
  • The recommendation appears to be backwards, and I recommend fixing that. You made a good argument for preferring cstdlib in cpp code and then recommended in the answer to prefer stdlib.h. Why? – shawn1874 Dec 29 '22 at 17:47
  • @shawn1874 Is it the sentence *"You should have a pretty strong argument to use stdlib.h instead of cstdlib"*? In that case I think you're interpreting it wrong. – klutt Dec 30 '22 at 08:48
  • @shawn1874 I clarified it a bit – klutt Dec 30 '22 at 09:03
  • @klutt, yes but I'm not sure how I'm misinterpreting it. It seems like that statement is contradictory since you are making a strong argument for using cstdlib in CPP code. – shawn1874 Dec 31 '22 at 14:21
  • @shawn1874 I simply do not see how it could be interpreted that way. It clearly says that the best choice is to use `cstdlib` and that you should have a good argument to not do it. – klutt Jan 01 '23 at 04:15