.\" Copyright (c) 2022 by Alejandro Colomar .\" .\" SPDX-License-Identifier: Linux-man-pages-copyleft .\" .TH static_assert 3 2023-10-31 "Linux man-pages 6.7" .SH NAME static_assert, _Static_assert \- fail compilation if assertion is false .SH LIBRARY Standard C library .RI ( libc ) .SH SYNOPSIS .nf .B #include .P .BI "void static_assert(scalar " constant-expression ", const char *" msg ); .P /* 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). .P If the input is nonzero, no code is emitted. .P .I msg must be a string literal. Since C23, this argument is optional. .P There's a keyword, .BR \%_Static_assert (), that behaves identically, and can be used without including .IR . .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. .P .in +4n .\" SRC BEGIN (must_be.c) .EX #include #include #include #include #include #include \& /* * 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)