44

Using C++11, is it better to #include <cassert> or <assert.h>? Or is there no difference?

Edit:

It seems Should I include <xxxx.h> or <cxxxx> in C++ programs? argues that it comes down to polluting the global namespace. Is this a special case because assert is a macro and there is no std::assert?

Community
  • 1
  • 1
TallBrianL
  • 1,230
  • 1
  • 9
  • 14
  • [Should I include stddef.h or cstddef for size_t](http://stackoverflow.com/q/5079325/995714), [Difference between string.h and cstring?](http://stackoverflow.com/q/8380805/995714), [What's the main difference between stdlib.h and cstdlib in C++?](http://stackoverflow.com/q/2847729/995714) – phuclv Mar 25 '17 at 04:16
  • @TallBrianL. As I stated in my answer and http://stackoverflow.com/questions/43011737/is-it-better-to-include-cassert-or-assert-h/43011792?noredirect=1#comment73114058_43011792. Neither is wrong, if you use assert.h your program will be backwards compatible with C, if you use cassert, it will definitely not be. – Santiago Varela Mar 25 '17 at 04:27
  • 3
    *@Santiago Varela* But C backwards compatible C++ code? How is that a thing? Backwards compatible C++ code is probably atrocious C++. Even the usual trivial hello world example uses `cout` which does not exist in C. In practice using the C-style include won’t gain you anything in terms of overall compatibility. – besc Mar 25 '17 at 08:30
  • @besc There is tons and tons of C legacy code. A lot of low level and older systems are coded in C. **C++ and C interoperability/portability** has been and will still be vitally important. http://stackoverflow.com/questions/4575192/why-is-c-backward-compatible-with-c-why-isnt-there-some-pure-c-language – Santiago Varela Mar 25 '17 at 12:41
  • 1
    *@Santiago Varela* I’m not questioning interoperability. Especially compiling C as C++ can be incredibly useful. And where would we be without C API layers to glue the world together? What I’m saying is: If you restrict your C++ to the C-compatible subset, then the language you write in is not C++ anymore, it’s C. At that point the question becomes moot because in C the choice between cassert and assert.h does not exist. – besc Mar 25 '17 at 15:49
  • C is no longer a subset of C++ anyway. – aschepler Mar 26 '17 at 01:25
  • I almost voted to reopen as `` is distinctly different than the other standard headers in that it defines only macros (which can't be limited to a namespace), but after reading the answers to both questions that distinction doesn't seem to make a difference. – Adrian McCarthy Mar 27 '17 at 20:10

2 Answers2

42

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.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • 7
    There is a proposal to undeprecate the C headers (I bet you are aware, but not everyone will be): http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0619r0.html#3.5 – Sjoerd Mar 25 '17 at 03:31
  • @Sjoerd: Excellent comment! This is a proposal for C++20. – Howard Hinnant Mar 25 '17 at 03:37
  • 4
    This answer is somewhat misleading, as it uses "C standard library header" to refer to C's version of ``, and then the same term to refer to C++'s version of it. To be clear, C defines a macro named `static_assert` in ``. C++ defines no such macro in either `` or ``. –  Mar 25 '17 at 13:00
  • "Both C++14 and C++17 define `` only by reference to their respective C specifications" -- [depr.c.headers]p2 is what states that C++'s `` is defined in terms of ``, which in turn is defined in terms of C's ``. Since `` lacks a `static_assert` macro and there is nothing adding it back to C++'s ``, C++'s `` lacks it as well. The only possible omission is that [depr.c.headers]p2 appears to import the `std`-namespace names, but nothing else. `assert` is a macro but should be defined by `` as well. –  Mar 27 '17 at 21:55
  • @hvd: Are you referring to the paragraph that begins: "The header behaves as if..." ? – Howard Hinnant Mar 27 '17 at 22:25
  • @HowardHinnant Sorry for the confusion, no, I'm referring to "Every other C header, each of which has a name of the form `name.h`, behaves as if [...]", which used to be p2 (with less wording), but is now p3. –  Mar 27 '17 at 22:28
  • @hvd: Ok. I think you're reading too much into that paragraph. 20.2 [library.c] introduces the C library and defers to the C standard for the detailed specification of those headers. 20.5.1.2 [headers]/p4 "Except as noted in..." pretty much says the opposite, defining the cname headers in terms of the name.h headers as specified in the C standard library. – Howard Hinnant Mar 27 '17 at 22:54
  • 1
    @HowardHinnant Again you're treating C's `` and C++'s `` as the same. They're not. C++'s `` is like C++'s ``, except for namespace, which are both different from C's ``. 20.2 covers C++'s ``. 20.5.1.2 refers to C's ``. There's no contradiction. For a case where it matters: C++'s `` adds overloads of `abs`. Those overloads are also visible even if only `` is included. Try it online to see how implementations treat it: http://coliru.stacked-crooked.com/a/515f21d12ce5f2ad –  Mar 28 '17 at 05:16
10

Looking at code:

Using assert.h   // Compatible with C language standard
---------------
#include <assert.h>

int main() {
    assert(true == true); // Execution continues
    assert(true == false); // Execution will abort with false value assert!
    return 0;
}

Using cassert    // Not compatible with C language standard
--------------
#include <cassert>

int main() {
    assert(true == true); // Execution continues
    assert(true == false); // Execution will abort with false value assert!
    return 0;
}

They both work!


Which one is better in C++11?

Regarding C++11's and C++17's specification:

C.5.1 (section from C++17 document)
Modifications to headers [diff.mods.to.headers]

  1. For compatibility with the C standard library, the C++ standard library provides the C headers enumerated in D.5, but their use is deprecated in C++.

  2. There are no C++ headers for the C headers , <stdnoreturn.h>, and <threads.h>, nor are the C headers themselves part of C++.

  3. The C++ headers (D.4.1) and (D.4.4), as well as their corresponding C headers and , do not contain any of the content from the C standard library and instead merely include other headers from the C++ standard library.


D.5 C standard library headers [depr.c.headers] 1. For compatibility with the C standard library, the C++ standard library provides the C headers shown in Table 141.

enter image description here

Both C++11 and C++17 standard specifications documents state the use of <X.h> remains for compatibility with the C standard, although their use is regarded as deprecated.


Regarding the C++ 20 standard proposal

They are reviewing "undeprecating" the use of the C library headers in C++20. <X.h> appear highlighted in green. C++11 and C++17 deprecation, as of now, is stated as a "weak recommendation" and a "tweak" for keeping the "C standard library headers (c.headers)" is displayed below:

"The basic C library headers are an essential compatibility feature, and not going anywhere anytime soon." (from C++ 20 review document)


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

Weak recommendation: In addition to the above, also remove the corresponding C headers from the C++ standard, much as we have no corresponding <stdatomic.h>, <stdnoreturn.h>, or <threads.h>, headers. As above, but with the following tweaks: 20.5.5.2.1 C standard library headers [c.headers]

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

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

The header <complex.h> behaves as if it simply includes the header . The header <tgmath.h> behaves as if it simply includes the headers <complex> and <cmath>.


Bjarne Stroustrup recommends maximising inter-operability between the C and C++ languages, by reducing imcompatibilities as much as possible. Others argue otherwise, as it complicates things.

So, it seems <X.h> aren't going anywhere. Ultimately, you can use both. Personally, I would make the decision of which one I would use boil down to having your code backwards compatible with C code or not.

Santiago Varela
  • 2,199
  • 16
  • 22
  • where did you get that ` headers already use and include headers`? [ headers just puts things in `std` namespace, and optionally in global namespace](http://stackoverflow.com/a/32606280/995714), [cstdio stdio.h namespace](http://stackoverflow.com/a/10460277/995714) – phuclv Mar 25 '17 at 02:55
  • 5
    *"As headers already use and include headers."* - This may be a common implementation that you've run into a lot, but it's not really a correct general statement. Nothing says that has to be the case. I mean, I'm looking at mingw's `` right now and [it does a lot more than just include `math.h`](http://pastebin.com/zSr81wD3). Other than that I don't see any real problems with this answer's wording. – Jason C Mar 25 '17 at 03:09
  • @Sjoerd, are you contributing to C++20? – Santiago Varela Mar 25 '17 at 03:50
  • @JasonC the headers are not required to include because they're not required to put things in the global namespace, although many do. OTOH are not required to put things in std namespace – phuclv Mar 25 '17 at 03:53
  • This answer has been cloned to the original question, so its value here seems limited. I suggest deleting this one and letting people find the other via the duplicate question link. – Adrian McCarthy Mar 27 '17 at 20:29
  • This was the original Q&A... – Santiago Varela Mar 27 '17 at 20:31