Why don't you simply define ASSERT differently depending on that macro?
#ifdef MACRO
#define ASSERT(NAME, TEST) \
do { \
printf("Assert failed"); \
} while(0)
#else
#define ASSERT(NAME, TEST) {}
#endif
Using fixed preprocessor values in C conditionals should be avoided - sure the compiler should optimise the dead code out, but why rely on that when you can essentially remove the actual C code?
EDIT:
There is a rather ugly trick involving macro argument stringification that you might be able to use:
#include <string.h>
#include <stdio.h>
#define X
#define ERROR_(NAME, TEXT) \
if (strcmp("", #NAME) == 0) \
printf("%s\n", TEXT)
#define ERROR(n, t) ERROR_(n, t)
int main() {
ERROR(X, "Error: X");
ERROR(Y, "Error: Y");
return 0;
}
This outputs:
$ ./test
Error: X
Essentially it uses the fact that when a preprocessor token is not defined as a macro, it expands to itself. When, on the other hand, it is defined it expands to either an empty string, or its definition. Unless one of your macros has its own name as a definition, this hack should work.
Disclaimer: Use this at your own risk!
(...because I will most certainly not use it!)
EDIT 2:
The assembly output of gcc -O0 -S for the program above is:
.file "test.c"
.section .rodata
.LC0:
.string "Error: X"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
movl $.LC0, %edi
call puts
movl $0, %eax
leave
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.4.3"
.section .note.GNU-stack,"",@progbits
Even with no optimisation, GCC reduces this program to a single puts() call. This program produces exactly the same assembly output:
#include <stdio.h>
int main() {
puts("Error: X");
return 0;
}
Therefore, you are probably not going to have any performance issues, depending on your compiler and any optimisations...