where BUILD_ASSERT() is defined as
#ifdef __cplusplus
#define BUILD_ASSERT(expr, msg) static_assert(expr, msg)
#else
#define BUILD_ASSERT(expr, msg) _Static_assert(expr, msg)
#endif
I could be missing something here, but I don't think that's needed.
C11 defines the static_assert macro already for C++ compatibility.
7.2 Diagnostics <assert.h>
The header <assert.h> defines the assert and static_assert macros and ...
I assumed we are talking about freestanding code here. In C, that includes only header files <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, and <stdnoreturn.h>. So, <assert.h> may or may not be available. However, _Static_assert() will be, if the compiler supports C11 or later.
The fact that the macro definition may look ugly as all hell, doesn't matter. What matters is that it's side effects are documented (none, here, for
BUILD_ASSERT() or
REQUIRE_ZERO() –– see the standard for the former; for the latter, because the expression is basically a
sizeof expression, no side effects in the expression will be applied: something like
REQUIRE_ZERO(--x) will not work, x will not be decremented), and that they are properly used to confirm build-time requirements if and when applicable.
Again, most important thing is to document the assumptions and requirements. I agree with ataradov's opinion on run-time checking such stuff, and consider the utmost priority to be to document all requirements and assumptions, with a weak preference on build-time tests verifying the ones that can be easily verified without runtime overhead, and avoiding run-time tests in embedded software. Things like "does this architecture use IEEE-754 Binary32 as
float?" are nontrivial to check (because there are architectures that seem to, but do not support subnormals), so documenting the requirements should always be the priority; and the build-time checks just trivial "hey, you forgot this" -type helpers for complex projects.
(In fully hosted environments, I prefer separate run-time test suites to included run-time tests; but, for highly portable code, letting the user know whoever built the binaries did it wrong, can sometimes be worth the overhead.)