2012-08-10 53 views
3

考慮宏擴展後重新掃描'defined'操作符:它應該工作嗎?

#define FOOBAR (defined(FOO) || defined(BAR)) 

#if FOOBAR 
/* Do stuff. */ 
#endif 

如若這項工作?我在問,因爲顯然我的編譯器沒有問題,但doxygen內部預處理器認爲#if存在語法錯誤。我知道我可以解決這個問題

#if defined(FOO) || defined(BAR) 
#define FOOBAR 1 
#endif 
#if FOOBAR 
/* Do stuff. */ 
#endif 

回答

4

從C99規格:

6.10.1.3

之前評價,在預處理標記的列表中,將成爲宏調用 的控制常量表達式被替換(除了那些宏名稱由定義的一元運算符修改爲 ),就像在普通文本中一樣。如果定義的令牌爲 作爲此替換過程的結果生成或使用定義的一元運算符 與宏替換之前的兩個指定表單中的一個不匹配,則行爲爲 未定義。

因此,如果您使用的宏如您所做的那樣擴展到defined,那麼結果是未定義的。

與C規範中大多數未定義的東西一樣,它的未定義因爲標準之前的實現以不同的方式處理它。

+0

+1,...或者委員會認爲編譯器實現者承擔了GCC預處理器手冊中特定錯誤條件 – 2012-08-10 19:50:26

+0

的負擔太多:'如果定義的操作符由於宏擴展而出現, C標準說行爲是不確定的。 GNU cpp將它視爲一個真正定義的運算符,並對其進行正常評估。如果您使用命令行選項「-pedantic」,它會警告您的代碼在哪裏使用此功能,因爲其他編譯器可能會以不同方式處理它。 – Johanness 2012-12-30 11:30:45

0

這聽起來像一個特定於編譯器的問題。只要你只是使用這個編譯器,就試試看 - 在/*do stuff*/部分放一些代碼,看看代碼是否被編譯。

+1

我不是一個真正的推論「它是如何工作的」,而是「它與我的特定編譯器是如何工作的」。這將構成*實驗編程*,我認爲這不是一個好的工程。由於C和預處理器行爲是在國際標準中規定的,所以我們應該在這裏尋找*明確*答案。 – Jens 2012-08-11 07:34:26