2012-05-21 45 views
10

下面的C++代碼編譯和工作按預期在GCC(4.0.4)預處理程序作爲參數傳遞給其他宏

#define FOO(x,y,z) ((x)*(y)*(z)) 
#define BAR(x) FOO(x,1) 
#define BAZ 3,7 

int main() 
{ 
    return BAR(BAZ); /* interpreted as return ((3)*(7)*(1)); */ 
} 

但是程序員,宏導致2010年微軟的Visual C++ Express中的錯誤:

main.cpp中(7):警告C4003:錯誤C2059:用於宏 'FOO'
main.cpp中(7)沒有足夠的實際參數語法錯誤: ')'

問題似乎是,Microsoft編譯器在內部處理BAR宏時,並未將BAZ宏擴展爲可用作宏FOO的兩個單獨參數的參數。

根據標準,哪個編譯器正確處理了這種情況?

+0

看起來像你真正想要的是[variadic宏](http://en.wikipedia.org/wiki/Variadic_macro)。 – leftaroundabout

+3

@leftaroundabout似乎並不像他...... –

+3

@iammilind:標準的第16章中缺少的是什麼?它怎麼不是一個「真正的」標準? –

回答

12

根據ISO/IEC的16.3.4 14882:

  1. 宏調用替換宏的替換列表(身體),其中每個參數名:2003,如下所示(C++參考標準)宏擴展進行(除非它受#或##影響)被宏調用中指定的相應參數的完整宏擴展替代。
  2. 步驟1的結果是重新掃描。如果其中有更多的宏調用(除了那些已經擴展的文本正在考慮之外),它們將按照相同的過程遞歸地擴展。

爲你指定的代碼步驟的順序是:

  1. BAR(BAZ)
  2. FOO(3,7,1)
  3. ((3)*(7)*(1))

因此GCC是正確的,而VC是沒有的。但VC抱怨的錯誤是FOO有3個參數,而BAR只指定了其中的2個。 VC顯然試圖儘快發現錯誤,並且有點過分。

+1

我不明白你給出的算法是如何對應於GCC行爲的。如果我正確地讀了它,算法如下:'BAR(BAZ)'是用'BAZ'參數調用'BAR',因此被替換爲'FO​​O(BAZ,1)'。這現在得到重新掃描。它找到的第一個宏是'FOO',所以現在它試圖用'BAZ'和'1'來擴展'FOO'。這是不夠的參數,所以預處理失敗。爲什麼重新掃描'FOO(BAZ,1)'擴展'BAZ',當掃描BAR(BAZ)時,首先擴展了BAR? – Mankarse

+0

@Mankarse謝謝,它確實不夠清楚。固定。 –

+0

感謝您的明確和完整的解釋。我學到了很多。 – Mankarse

相關問題