summaryrefslogtreecommitdiffstats
path: root/man3/static_assert.3
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--man3/static_assert.3119
1 files changed, 119 insertions, 0 deletions
diff --git a/man3/static_assert.3 b/man3/static_assert.3
new file mode 100644
index 0000000..86c6673
--- /dev/null
+++ b/man3/static_assert.3
@@ -0,0 +1,119 @@
+.\" Copyright (c) 2022 by Alejandro Colomar <alx@kernel.org>
+.\"
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
+.\"
+.TH static_assert 3 2023-05-03 "Linux man-pages 6.05.01"
+.SH NAME
+static_assert, _Static_assert \- fail compilation if assertion is false
+.SH LIBRARY
+Standard C library
+.RI ( libc )
+.SH SYNOPSIS
+.nf
+.B #include <assert.h>
+.PP
+.BI "void static_assert(scalar " constant-expression ", const char *" msg );
+.PP
+/* Since C23: */
+.BI "void static_assert(scalar " constant-expression );
+.fi
+.SH DESCRIPTION
+This macro is similar to
+.BR \%assert (3),
+but it works at compile time,
+generating a compilation error (with an optional message)
+when the input is false (i.e., compares equal to zero).
+.PP
+If the input is nonzero,
+no code is emitted.
+.PP
+.I msg
+must be a string literal.
+Since C23, this argument is optional.
+.PP
+There's a keyword,
+.BR \%_Static_assert (),
+that behaves identically,
+and can be used without including
+.IR <assert.h> .
+.SH RETURN VALUE
+No value is returned.
+.SH VERSIONS
+In C11,
+the second argument
+.RI ( msg )
+was mandatory;
+since C23,
+it can be omitted.
+.SH STANDARDS
+C11 and later.
+.SH EXAMPLES
+.BR static_assert ()
+can't be used in some places,
+like for example at global scope.
+For that,
+a macro
+.BR \%must_be ()
+can be written in terms of
+.BR \%static_assert ().
+The following program uses the macro to get the size of an array safely.
+.PP
+.in +4n
+.\" SRC BEGIN (must_be.c)
+.EX
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+\&
+/*
+ * This macro behaves like static_assert(), failing to
+ * compile if its argument is not true. However, it always
+ * returns 0, which allows using it everywhere an expression
+ * can be used.
+ */
+#define must_be(e) \e
+( \e
+ 0 * (int) sizeof( \e
+ struct { \e
+ static_assert(e); \e
+ int ISO_C_forbids_a_struct_with_no_members; \e
+ } \e
+ ) \e
+)
+\&
+#define is_same_type(a, b) \e
+ __builtin_types_compatible_p(typeof(a), typeof(b))
+\&
+#define is_array(arr) (!is_same_type((arr), &*(arr)))
+#define must_be_array(arr) must_be(is_array(arr))
+\&
+#define sizeof_array(arr) (sizeof(arr) + must_be_array(arr))
+#define nitems(arr) (sizeof((arr)) / sizeof((arr)[0]) \e
+ + must_be_array(arr))
+\&
+int foo[10];
+int8_t bar[sizeof_array(foo)];
+\&
+int
+main(void)
+{
+ for (size_t i = 0; i < nitems(foo); i++) {
+ foo[i] = i;
+ }
+\&
+ memcpy(bar, foo, sizeof_array(bar));
+\&
+ for (size_t i = 0; i < nitems(bar); i++) {
+ printf("%d,", bar[i]);
+ }
+\&
+ exit(EXIT_SUCCESS);
+}
+.EE
+.\" SRC END
+.in
+.SH SEE ALSO
+.BR assert (3)