]> git.ipfire.org Git - thirdparty/man-pages.git/commitdiff
_Static_assert.3, static_assert.3: Add documentation for static_assert()
authorAlejandro Colomar <alx@kernel.org>
Fri, 2 Dec 2022 15:11:46 +0000 (16:11 +0100)
committerAlejandro Colomar <alx@kernel.org>
Fri, 2 Dec 2022 15:11:46 +0000 (16:11 +0100)
Signed-off-by: Alejandro Colomar <alx@kernel.org>
man3/_Static_assert.3 [new file with mode: 0644]
man3/static_assert.3 [new file with mode: 0644]

diff --git a/man3/_Static_assert.3 b/man3/_Static_assert.3
new file mode 100644 (file)
index 0000000..30f6353
--- /dev/null
@@ -0,0 +1 @@
+.so man3/static_assert.3
diff --git a/man3/static_assert.3 b/man3/static_assert.3
new file mode 100644 (file)
index 0000000..379bd2b
--- /dev/null
@@ -0,0 +1,118 @@
+.\" Copyright (c) 2022 by Alejandro Colomar <alx@kernel.org>
+.\"
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
+.\"
+.TH static_assert 3 (date) "Linux man-pages (unreleased)"
+.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
+.in
+.SH SEE ALSO
+.BR assert (3)