diff options
Diffstat (limited to '')
-rw-r--r-- | man3/static_assert.3 | 119 |
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) |