Detecting if an expression is constant in C 21 Apr 2025 Here's a fun little language puzzle: implement a macro that takes an expression as an argument and: Verifies that the expression is a constant expression (i.e, known at compile time), otherwise aborts the compilation. "Returns" back the same value. Optionally, the returned value has the same type as the original expression. There's a number of ways to solve this, depending on which C standard you're using and whether compiler extensions are allowed or not. Here are a few I've come across along with some pros and cons. static compound literals If you're using C23 or later then you can specify a storage duration for compound literals combined with typeof (also standardized in C23). #define C(x) ( (static typeof(x)){x} ) This keeps the same type, and since initializers of static storage duration need to be constant expression, the compiler will ensure that x is a constant expression. Cons: Requires C23, which isn't widely supported as of this writing. Clang (v20) doesn't seem to support static in compound literals just yet (GCC v14.2 seems to work). __builtin_constant_p If using GNU extensions is not a problem, then you can use __builtin_constant_p, which returns true when an expression is constant. __attribute((error("not constant"))) int notconst(void); #define C(x) ((__typeof__(x)) \ ((x) + __builtin_constant_p(x) ? 0 : notconst()) \ ) When __builtin_constant_p returns true, it adds 0 to the value, leaving it unchanged. Otherwise, it calls a dummy non-existent function declared with the error attribute, causing a compilation error. However, since the addition will end up performing the usual integer promotion, the type of the result may be different. That's why there's a __typeof__(x) cast, to keep the same type. Cons: static_assert This trick was shown to me by constxd in an IRC channel and uses C11+ static_assert to ensure the expression is static. But how do we "return" the expression back? Well... with a bi...
First seen: 2025-04-22 17:41
Last seen: 2025-04-22 23:42