Print expanded macro values at compile-time
This is an extension of @Jackie Yeh's answer here.
The magic helper macros, with my minor tweaks:
// Helper macros to print the value of a macro at compile-time
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define PRINT_MACRO_AT_COMPILE_TIME(var) #var "=`" VALUE(var) "`"
To use them:
#pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_INT)
A word of caution: if the macro is not defined, its name will just be printed out again! So, if your macro is called MY_MACRO
, but you never define it, then doing this:
#pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_MACRO)
...will print out something like this:
../main.c:1000:63: note: #pragma message: MY_MACRO=`MY_MACRO`
So, look for MY_MACRO=`MY_MACRO`
type output when compiling as a clear sign that MY_MACRO
is not defined!
This threw me off for a while and I lost a lot of time not realizing this.
I want to show that this works with code blocks too. So, here's my full example:
macro_print_macro_values_at_compile_time.c
from my eRCaGuy_hello_world repo:
///usr/bin/env ccache gcc -Wall -Wextra -Werror -O3 -std=gnu17 "$0" -o /tmp/a -lm && /tmp/a "$@"; exit
// For the line just above, see my answer here: https://mcmap.net/q/12603/-run-c-or-c-file-as-a-script
#include <stdbool.h> // For `true` (`1`) and `false` (`0`) macros in C
#include <stdint.h> // For `uint8_t`, `int8_t`, etc.
#include <stdio.h> // For `printf()`
// Various macro definitions to test
#define DEFINED_BUT_NO_VALUE
#define MY_INT 3
#define MY_STR "ABC"
#define MY_CODE_BLOCK \
do \
{ \
printf("Hi 1.\n"); \
} while (0)
//
// NB: the `#pragma message` output of the above macro is substantially different if I define it as
// `MY_CODE_BLOCK()` instead, and call it as such inside `main()`! Try it out and you'll see.
//
#define MY_CODE_BLOCK2 \
{ \
printf("Hi 2.\n"); \
}
// Helper macros to print the value of a macro at compile-time
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define PRINT_MACRO_AT_COMPILE_TIME(var) #var "=`" VALUE(var) "`"
// Example prints at compile-time
#pragma message PRINT_MACRO_AT_COMPILE_TIME(NOT_DEFINED)
#pragma message PRINT_MACRO_AT_COMPILE_TIME(DEFINED_BUT_NO_VALUE)
#pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_INT)
#pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_STR)
#pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_CODE_BLOCK)
#pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_CODE_BLOCK2)
// int main(int argc, char *argv[]) // alternative prototype
int main()
{
MY_CODE_BLOCK;
MY_CODE_BLOCK2;
printf("Hello World.\n\n");
return 0;
}
Build and run commands, and output, in both C and C++:
In C:
eRCaGuy_hello_world/c$ ./macro_print_macro_values_at_compile_time.c
./macro_print_macro_values_at_compile_time.c:74:9: note: ‘#pragma message: NOT_DEFINED=`NOT_DEFINED`’
74 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(NOT_DEFINED)
| ^~~~~~~
./macro_print_macro_values_at_compile_time.c:75:9: note: ‘#pragma message: DEFINED_BUT_NO_VALUE=``’
75 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(DEFINED_BUT_NO_VALUE)
| ^~~~~~~
./macro_print_macro_values_at_compile_time.c:76:9: note: ‘#pragma message: MY_INT=`3`’
76 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_INT)
| ^~~~~~~
./macro_print_macro_values_at_compile_time.c:77:9: note: ‘#pragma message: MY_STR=`"ABC"`’
77 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_STR)
| ^~~~~~~
./macro_print_macro_values_at_compile_time.c:78:9: note: ‘#pragma message: MY_CODE_BLOCK=`do { printf("Hi 1.\n"); } while (0)`’
78 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_CODE_BLOCK)
| ^~~~~~~
./macro_print_macro_values_at_compile_time.c:79:9: note: ‘#pragma message: MY_CODE_BLOCK2=`{ printf("Hi 2.\n"); }`’
79 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_CODE_BLOCK2)
| ^~~~~~~
Hi 1.
Hi 2.
Hello World.
Or, in C++:
eRCaGuy_hello_world/c$ g++ -Wall -Wextra -Werror -O3 -std=gnu++17 macro_print_macro_values_at_compile_time.c -o bin/a && bin/a
macro_print_macro_values_at_compile_time.c:71:63: note: ‘#pragma message: NOT_DEFINED=`NOT_DEFINED`’
71 | #define PRINT_MACRO_AT_COMPILE_TIME(var) #var "=`" VALUE(var) "`"
| ^~~
macro_print_macro_values_at_compile_time.c:74:17: note: in expansion of macro ‘PRINT_MACRO_AT_COMPILE_TIME’
74 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(NOT_DEFINED)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
macro_print_macro_values_at_compile_time.c:71:63: note: ‘#pragma message: DEFINED_BUT_NO_VALUE=``’
71 | #define PRINT_MACRO_AT_COMPILE_TIME(var) #var "=`" VALUE(var) "`"
| ^~~
macro_print_macro_values_at_compile_time.c:75:17: note: in expansion of macro ‘PRINT_MACRO_AT_COMPILE_TIME’
75 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(DEFINED_BUT_NO_VALUE)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
macro_print_macro_values_at_compile_time.c:71:63: note: ‘#pragma message: MY_INT=`3`’
71 | #define PRINT_MACRO_AT_COMPILE_TIME(var) #var "=`" VALUE(var) "`"
| ^~~
macro_print_macro_values_at_compile_time.c:76:17: note: in expansion of macro ‘PRINT_MACRO_AT_COMPILE_TIME’
76 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_INT)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
macro_print_macro_values_at_compile_time.c:71:63: note: ‘#pragma message: MY_STR=`"ABC"`’
71 | #define PRINT_MACRO_AT_COMPILE_TIME(var) #var "=`" VALUE(var) "`"
| ^~~
macro_print_macro_values_at_compile_time.c:77:17: note: in expansion of macro ‘PRINT_MACRO_AT_COMPILE_TIME’
77 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_STR)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
macro_print_macro_values_at_compile_time.c:71:63: note: ‘#pragma message: MY_CODE_BLOCK=`do { printf("Hi 1.\n"); } while (0)`’
71 | #define PRINT_MACRO_AT_COMPILE_TIME(var) #var "=`" VALUE(var) "`"
| ^~~
macro_print_macro_values_at_compile_time.c:78:17: note: in expansion of macro ‘PRINT_MACRO_AT_COMPILE_TIME’
78 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_CODE_BLOCK)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
macro_print_macro_values_at_compile_time.c:71:63: note: ‘#pragma message: MY_CODE_BLOCK2=`{ printf("Hi 2.\n"); }`’
71 | #define PRINT_MACRO_AT_COMPILE_TIME(var) #var "=`" VALUE(var) "`"
| ^~~
macro_print_macro_values_at_compile_time.c:79:17: note: in expansion of macro ‘PRINT_MACRO_AT_COMPILE_TIME’
79 | #pragma message PRINT_MACRO_AT_COMPILE_TIME(MY_CODE_BLOCK2)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
Hi 1.
Hi 2.
Hello World.
Adjacently-related
- My answer on Printing the size of (
sizeof()
) a type or variable in an error message at compile time in both C and C++
sizeof()
at compile time in C? – Bronco