簡體   English   中英

c預編譯器對定義為(void)0的宏做了什么

[英]What does the c precompiler do with macros defined as (void)0

我有一些基於編譯器標志定義的宏。 我正在嘗試決定是否要將宏定義為(void)0或將其定義為未定義並導致編譯時錯誤。

#ifdef DEBUG
  #define PRINTF(...) printf(__VA_ARGS__)
#else
  #define PRINTF(...) (void)0
#endif

int main(void) {
  ...
  PRINTF("something");
  ...
}

#ifdef DEBUG
  #define PRINTF(...) printf(__VA_ARGS__)
#endif

int main(void) {
  ...
  #ifdef DEBUG
    PRINTF("something");
  #endif
  ...
}

我不確定我喜歡哪種技術。 一方面用#ifdef包裝每個PRINTF語句都很難看。 另一方面,如果我已經調用了一個在上下文中不起作用的函數,那么在編譯時就知道了。

我認為決定因素是(void)0宏是否會影響可執行文件的大小。

編譯代碼時,(void)0會發生什么? 如果PRINTF定義為(void)0,那是否意味着可執行文件將包含某種(void)0指令或是否會被完全忽略?

(void) 0;

是一個沒有副作用的表達式語句。 任何理智的實現都會優化這個語句(實現可以用這樣的語句做什么?)。

如果定義了NDEBUG則將(void) 0作為宏定義得到C標准的認可,因為它出現在(C11)7.2p1中,用於assert宏定義:

#define assert(ignore) ((void)0)

注意定義:

#define PRINTF(...) (void)0

代替

#define PRINTF(...)

有一個優勢。 在第一種情況下,您有一個表達式(就像一個不返回值的函數),因此它可用於例如逗號表達式或條件表達式中。

例如:

// Comma expression
printf("test"), PRINTF("Hi Dennis");

// Conditional expression
test-expr ? perror("Hello") : PRINTF("world");

這兩個表達式語句僅對前PRINTF定義有效(帶(void) 0 )。

它將被完全忽略,您可以通過查看匯編輸出( gcc -S將生成file.s,asm輸出)來確認這一點,使用和不使用(void)0行進行比較並看到它完全相同。

一個中等體面的編譯器將優化掉死(不可達)代碼,因此您可以:

  #ifdef DEBUG
  #define PRINTF(...) if (1) { printf(__VA_ARGS__) ; }
  #else
  #define PRINTF(...) if (0) { printf(__VA_ARGS__) ; }
  #endif

它具有允許編譯器檢查調試代碼的巨大優勢,無論您是否正在使用/未啟用DEBUG - 這樣可以降低在您的背面留下痛苦牙齒痕跡的風險。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM