The ‘verify’ module supports compile-time tests, as opposed to
the standard assert macro which supports only runtime tests.
Since the tests occur at compile-time, they are more reliable, and
they require no runtime overhead.
This module provides a header file verify.h that defines two
macros: verify (V) and verify_expr
(V, EXPR). Both accept an integer constant expression
argument V and verify that it is nonzero. If not, a compile-time error
results.
verify (V); is a declaration; it can occur outside of
functions. In contrast, verify_expr (V, EXPR) is
an expression that returns the value of EXPR; it can be used in
macros that expand to expressions. If EXPR is an integer
constant expression, then verify_expr (V, EXPR) is
also an integer constant expression. Although EXPR and
verify_expr (V, EXPR) are guaranteed to have the
same side effects and value and type (after integer promotion), they
need not have the same type if EXPR's type is an integer that is
narrower than int or unsigned int.
V should be an integer constant expression in the sense
of the C standard. Its leaf operands should be integer, enumeration,
or character constants; or sizeof expressions that return
constants; or floating constants that are the immediate operands of
casts. Outside a sizeof subexpression, V should
not contain any assignments, function calls, comma operators, casts to
non-integer types, or subexpressions whose values are outside the
representable ranges for their types. If V is not an
integer constant expression, then a compiler might reject a usage like
‘verify (V);’ even when V is
nonzero.
Although the standard assert macro is a runtime test, C11
specifies a builtin _Static_assert (V,
STRING-LITERAL), its assert.h header has a similar macro
named static_assert, and C++11 has a similar
static_assert builtin. These builtins and macros differ
from verify in two major ways. First, they can also be used
within a struct or union specifier, in place of an
ordinary member declaration. Second, they require the programmer to
specify a compile-time diagnostic as a string literal.
Here are some example uses of verify and verify_expr.
#include <verify.h>
#include <limits.h>
#include <time.h>
/* Verify that time_t is an integer type. */
verify ((time_t) 1.5 == 1);
/* Verify that time_t is no smaller than int. */
verify (sizeof (int) <= sizeof (time_t));
/* Verify that time_t is signed. */
verify ((time_t) -1 < 0);
/* Verify that time_t uses two's complement representation. */
verify (~ (time_t) -1 == 0);
/* Return the maximum value of the integer type T,
verifying that T is an unsigned integer type.
The cast to (T) is outside the call to verify_expr
so that the result is of type T
even when T is narrower than unsigned int. */
#define MAX_UNSIGNED_VAL(t) \
((T) verify_expr (0 < (T) -1, -1))