Environment:
$ g++ --version
g++ (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0
It is known that function-like macro assert
for debugging can be disabled with NDEBUG
defined before the include of assert.h
(cassert
). However, reading /usr/include/assert.h
in my environment, I found the code below.
#if defined __cplusplus && __GNUC_PREREQ (2,95)
# define __ASSERT_VOID_CAST static_cast<void>
#else
# define __ASSERT_VOID_CAST (void)
#endif
#ifdef NDEBUG
# define assert(expr) (__ASSERT_VOID_CAST (0))
# ifdef __USE_GNU
# define assert_perror(errnum) (__ASSERT_VOID_CAST (0))
# endif
#else /* Not NDEBUG. */
So, even with NDEBUG
, assert
is expanded into some value and thus affect the performance insignificantly but certainly (if no optimization occurs after the preprocess step). Since C++ standard allows function-like macro with empty value, it seems
#ifdef NDEBUG
#define assert(expr)
#endif
would be a good implementation.
Is there any reason why non-empty value should be the option?
The assert() macro is used to check expressions that ought to be true as long as the program is running correctly. It is a convenient way to insert sanity checks.
The assert() function tests the condition parameter. If it is false, it prints a message to standard error, using the string parameter to describe the failed condition. It then sets the variable _assert_exit to one and executes the exit statement. The exit statement jumps to the END rule.
Answer: An assert in C++ is a predefined macro using which we can test certain assumptions that are set in the program. When the conditional expression in an assert statement is set to true, the program continues normally. But when the expression is false, an error message is issued and the program is terminated.
The assert macro prints a diagnostic message when expression evaluates to false (0) and calls abort to stop program execution. No action is taken if expression is true (nonzero). The diagnostic message includes the failed expression, the name of the source file and line number where the assertion failed.
One reason that the macro has a value when NDEBUG
is defined is because the C standard requires that it has one — it even stipulates what it shall be.
§7.2 Diagnostics
<assert.h>
¶1 The header
<assert.h>
defines theassert
andstatic_assert
macros and refers to another macro,NDEBUG
which is not defined by
<assert.h>
. IfNDEBUG
is defined as a macro name at the point in the source file where<assert.h>
is included, theassert
macro is defined simply as#define assert(ignore) ((void)0)
The
assert
macro is redefined according to the current state ofNDEBUG
each time that<assert.h>
is included.¶2 The
assert
macro shall be implemented as a macro, not as an actual function. If the macro definition is suppressed in order to access an actual function, the behavior is undefined.…
7.2.1.1 The
assert
macroSynopsis
#include <assert.h> void assert(scalar expression);
Description
¶2 The
assert
macro puts diagnostic tests into programs; it expands to avoid
expression. When it is executed, ifexpression
(which shall have a scalar type) is false (that is, compares equal to 0), theassert
macro writes information about the particular call that failed (including the text of the argument, the name of the source file, the source line number, and the name of the enclosing function -- the latter are respectively the values of the preprocessing macros__FILE__
and__LINE__
and of the identifier__func__
) on the standard error stream in an implementation-defined format.191) It then calls theabort
function.Returns
¶3 The
assert
macro returns no value.191) The message written might be of the form:
Assertion failed: expression, function abc, file xyz, line nnn.
The C++11 standard says (§19.3 Assertions) says:
The header
<cassert>
… provides a macro for documenting C++ program assertions and a mechanism for disabling the assertion checks.…
The contents are the same as the Standard C library header
<assert.h>
.
So the same rules apply to C++ as to C. The C++ standard doesn't explicitly call out the differences between the C++ static_assert
and the C _Static_assert
(and the definition of static_assert
as _Static_assert
in the C version of the <assert.h>
header). The net result is much the same, though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With