类似函数的宏
类似函数的宏类似于 inline
函数,这些函数在某些情况下很有用,例如临时调试日志:
#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;
}
在这两种情况下(使用 DEBUG
或不使用 DEBUG
),调用的行为与使用 void
返回类型的函数相同。这确保了 if/else
条件被解释为预期。
在 DEBUG
案例中,这是通过 do { ... } while(0)
构造实现的。在另一种情况下,(void)0
是一个没有副作用的声明,只是被忽略了。
后者的另一种选择是
#define LOG(LINE) do { /* empty */ } while (0)
这使得它在所有情况下在语法上等同于第一个。
如果使用 GCC,还可以实现类似函数的宏,该宏使用非标准 GNU 扩展返回结果 - 语句表达式 。例如:
#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);
}