類似函式的巨集

類似函式的巨集類似於 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);
}