Side topic: Didn't we have a is_const_eval equivalent in C? I seem to remember a dark magic macro doing precisely that on the lkml somewhere, but can't find it.
The compiler constant folds fairly effectively anyway.
It's not exactly the same thing, but it's probably what you were thinking of.
#define QEMU_BUILD_BUG_ON(x) \
typedef char qemu_build_bug_on[(x)?-1:1] __attribute__((unused));
So you can write stuff like: QEMU_BUILD_BUG_ON(sizeof (struct foo) == 128);
(for example if the struct is used for some network protocol and so it must be 128 bytes long). #define QEMU_BUILD_BUG_MSG(x, msg) _Static_assert(!(x), msg)
#define QEMU_BUILD_BUG_ON(x) QEMU_BUILD_BUG_MSG(x, "not expecting: " #x)Starting with C11, it's possible to implement it without any non-standard extensions: https://stackoverflow.com/a/49480926
compile-time evaluation was introduced in C++11 and expanded in subsequent versions of the language standard.
Doing
const int X = 33;
// ...
void something() {
int arr[X] = ...
}
works in both C and C++, but with a catch: in C++, X is evaluated at compile time (it has internal linkage), while in C this works only after C99 because it's actually a VLA.const int X = 33;
enum { Y = X };
$ clang -o cs cs.c -Wall -std=c11 -pedantic
cs.c:6:6: warning: expression is not an integer constant expression; folding it to a constant is a GNU extension [-Wgnu-folding-constant]
A = X,
$ gcc -o cs cs.c -Wall -std=c11
cs.c:6:9: error: enumerator value for ‘A’ is not an integer constant
6 | A = X,
| ^
In general, that's illegal ISO C and should always be rejected, but as you see that's not usually the case.