考慮以下宏定義和調用:爲什麼參數替換在重新掃描期間不被替換?
#define x x[0]
#define y(arg) arg
y(x)
這種調用擴展爲x[0]
(上的Visual C++ 2010測試,克++ 4.1,MCPP 2.7.2和Wave)。
爲什麼?具體來說,它爲什麼不擴大到x[0][0]
?
在宏替換,
替換列表中的參數...被相應的參數,替換後包含的所有宏已經擴大。在被替換前,每個參數的預處理標記完全被宏代替(C++ 03§16.3.1/ 1)。
評估的宏調用,我們採取以下步驟:
- 的函數宏
y
被調用,x
作爲論據的arg
參數 - 在論證的
x
是宏替換爲x[0]
- 替換列表中的
arg
被替換爲參數的宏替換值
替換所有參數後的替換列表爲x[0]
。
在替換列表中的所有參數都被替換之後,所得到的預處理標記序列被重新掃描......以取代更多宏名稱(C++ 03§16.3.4/ 1)。
如果在掃描替換列表期間發現正在替換的宏的名稱...它不會被替換。此外,如果任何嵌套替換遇到被替換的宏的名稱,它不會被替換(C++ 03§16.3.4/ 2)。
列表x[0]
重新掃描更換(注意宏的名稱被替換是y
):
x
被識別爲類似對象的宏調用x
被替換通過x[0]
替換sto ps,因爲§16.3.4/ 2中的規則阻止了遞歸。重新掃描後的替換列表是x[0][0]
。
因爲我測試過的所有預處理器都說我錯了,所以我已經明確地誤解了一些東西。另外,這個例子是C++ 0x FCD(§16.3.5/ 5)中的一個更大的例子,它也表示預期的替換是x[0]
。
爲什麼x
在重新掃描過程中沒有被替換?
C99和C++ 0x實際上與引用段中的C++ 03具有相同的措詞。
啊哈!我忘記了'x'的替換列表在它被替換之前會被重新掃描;現在這一切都有道理。謝謝,史蒂夫。 – 2010-06-01 13:06:00