#define _H4X0R_CONVERT_ONE(arg) \
((union { unsigned long long u; void *v; }){ \
.u = (unsigned long long)arg, \
}).v
Couldn't this be just #define _H4X0R_CONVERT_ONE(arg) (void*)(uintptr_t)(arg)
?Also, thanks, now I can finally use
void my_printf(const char *fmt, void* args[], size_t argc);
ergonomically: #define my_printf(fmt, ...) (my_printf)((fmt), \
(void*[]){ H4X0R_VA_VOID_STAR_CONVERT(__VA_ARGS__) }, \
H4X0R_VA_COUNT(__VA_ARGS__))
int main(int argc, char **argv) {
my_printf("int: %d, ptr: %p, str: %s, missing: %d\n", 42, argv, "Hello world!");
}
$ gcc test.c && ./a.out
int: 42, ptr: 0x7FFF46AA3E78, str: Hello world!, missing: %!d(MISSING)
Funnily enough, the difference between passing ... and locally-allocated void*[] is basically who has to spill the data to the stack, the caller or the called function.