I'm migrating my codebase from C17 to C23 on ARM-GCC and would like to be able to print the evaluation of constexpr
calculations at compile-time for debugging purposes.
In C17, I used #pragma message
with a stringified, expanded version of my macro. Trying this in C23 using arm-none-eabi-gcc version 14.2.Rel1
I've seen some examples using templates with C++ but obviously that won't work for C.
For example, define printing vs. constexpr printing:
#define VALUE1 10
#define VALUE2 (VALUE1 + 5)
#define DEFINE_VALUE (VALUE2 * 2)
constexpr int val1 = 10;
constexpr int val2 = val1 + 5;
constexpr int constexpr_val = val2 * 2;
#define EXPAND(x) x
#define DEFINE_VALUE_EXPANDED EXPAND(DEFINE_VALUE)
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#pragma message("DEFINE_VALUE_EXPANDED is " TOSTRING(DEFINE_VALUE_EXPANDED))
#pragma message("constexpr_val is " TOSTRING(constexpr_val))
Results in:
src/io/test.c:130:9: note: '#pragma message: DEFINE_VALUE_EXPANDED is ((10 + 5) * 2)'
130 | #pragma message("DEFINE_VALUE_EXPANDED is " TOSTRING(DEFINE_VALUE_EXPANDED))
| ^~~~~~~
src/io/test.c:131:9: note: '#pragma message: constexpr_val is constexpr_val'
131 | #pragma message("constexpr_val is " TOSTRING(constexpr_val))
| ^~~~~~~
Ideally would print 30
in both cases. The way the define prints is ok, but the constexpr is printing as the string itself.
The C standard does not provide a way to display the results of constant expressions at compile time. With GCC and Clang, you do this using the __asm__
construct with an immediate operand, discussed here and here.