Function-like macros
suggest changeFunction-like macros are similar to inline
functions, these are useful in some cases, such as temporary debug log:
#ifdef DEBUG # define LOGFILENAME "/tmp/logfile.log" # define LOG(str) do { \ FILE *fp = fopen(LOGFILENAME, "a"); \ if (fp) { \ fprintf(fp, "%s:%d %s\n", __FILE__, __LINE__, \ /* don't print null pointer */ \ str ?str :"<null>"); \ fclose(fp); \ } \ else { \ perror("Opening '" LOGFILENAME "' failed"); \ } \ } while (0) #else /* Make it a NOOP if DEBUG is not defined. */ # define LOG(LINE) (void)0 #endif
#include <stdio.h> int main(int argc, char* argv[]) { if (argc > 1) LOG("There are command line arguments"); else LOG("No command line arguments"); return 0; }
Here in both cases (with DEBUG
or not) the call behaves the same way as a function with void
return type. This ensures that the if/else
conditionals are interpreted as expected.
In the DEBUG
case this is implemented through a do { ... } while(0)
construct. In the other case, (void)0
is a statement with no side effect that is just ignored.
An alternative for the latter would be
#define LOG(LINE) do { /* empty */ } while (0)
such that it is in all cases syntactically equivalent to the first.
If you use GCC, you can also implement a function-like macro that returns result using a non-standard GNU extension — statement expressions. For example:
#include <stdio.h> #define POW(X, Y) \ ({ \ int i, r = 1; \ for (i = 0; i < Y; ++i) \ r *= X; \ r; \ // returned value is result of last operation }) int main(void) { int result; result = POW(2, 3); printf("Result: %d\n", result); }
Found a mistake? Have a question or improvement idea?
Let me know.
Table Of Contents