2011-11-30 123 views
2

在使用「宏定義集1」執行以下代碼時,遇到錯誤「C2065:'C1':未聲明的標識符」。C/C++預處理歧義

在使用「宏定義設置2」,代碼運行給予的2

輸出我猜它是與預處理符號化。請解釋。

#include <iostream> 

// Macro Definitions Set 1 
#define A  1 
#define D(n) B(n) 
#define B(n) C##n 
#define CA  2 

// Macro Definitions Set 2 
//#define A  1 
//#define D(n) C##n 
//#define CA  2 

int main() 
{ 

    printf ("%d", D(A)); 
} 
+0

一個類似的問題,在這裏有相同的答案:http://stackoverflow.com/a/2751891/6210 – MSN

回答

3

宏參數被替換,除非它在##之前或之後,或者在#之後。

因此,在組1中,D(A)在替換D(n)之後變爲B(1),其在重新掃描之後替換爲C1

在集2,D(A)變得CA,其中A不是取代的,因爲它是##後,和CA後重新掃描變得2

0

您需要經過決議期間的每個階段。基本上,預處理器會進行迭代搜索和替換,直到耗盡令牌(它可能更復雜,但對於當前目的而言,這就是發生的情況)。它在每一行上從左到右。現在

,結果會怎樣使用設置2:

  • printf("%d", D(A)); < - 發現第一預處理記號是D(A),所以:
  • printf("%d", CA);
  • printf("%d", 2);

什麼似乎與可發生套1:

  • printf("%d", D(A)); < - 發現第一預處理記號是D(A),所以:
  • printf("%d", B(A)); < - 現在,找到了下一個標記是A
  • printf("%d", B(1));
  • printf("%d", C1); < - 和錯誤

的問題是發生替換,然後預處理器找到下一個(可能不重新啓動該行)A並執行另一個替換。然後它再次檢查它,但發現B(1)

爲了測試這個,你可以省略一些稍後的聲明並預處理到一個文件。這將告訴你到底發生了什麼。

+0

參數在整個函數樣式宏之前被處理,因此在'D(A)'中,第一個'A'代入'1'(在擴展中不存在'#'或'##'),則D(1)變爲'B(1)'。 – fefe

+0

你還沒有提到'##'運算符,這是關鍵 - 這是'##'運算符,它阻止'A'變成'1'。 – caf

2

有了您的第一組宏:

#define A  1 
#define D(n) B(n) 
#define B(n) C##n 
#define CA  2 

D(A)通過對A執行宏替換,然後將其代入替換名單D(n)評估。宏替換結果爲1,所以這給出B(1)。然後遞歸地評估B(1),給出C##1,其連接到預處理令牌C1

您的第二組宏:

#define A  1 
#define D(n) C##n 
#define CA 2 

D(A)進行評估,在參數n宏替換是進行,因爲它是由##前綴。這給出C##A,這導致預處理令牌CA。然後重新檢查宏以替換,結果爲2

+0

感謝您的解釋:) – sg1