程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> GCC擴展符(#,##)

GCC擴展符(#,##)

編輯:C++入門知識

    先來說說這兩個擴展符的各自用處吧,“#”是將宏字符串化(Stringification),“##”是將##左右兩邊的標簽組合在一起(token pasting or token concatenation),下面從兩個簡單例子著手: [cpp]   #define SSVAR(X,Y) const char X[]=#Y   SSVAR(InternetGatewayDevice, InternetGatewayDevice.);     上面這個例子實質是借用了#擴展符去實現名為InternetGatewayDevice的字符數組初始化,其等價代碼(可以通過gcc –E展開獲得)如下: [cpp]   const char InternetGatewayDevice[]="InternetGatewayDevice.";      下面這個例子比較常見,用於打開不同的路徑。 [cpp]   #define DEV_FILE_NAME    "/dev/test_kft"      #define OPEN_FILE(fd, n) \   {  \         fd = open(DEV_FILE_NAME ##n, 0); \      if (fd < 0) \      { \         printf("Open device error/n"); \         return 0; \      } \   }   OPEN_FILE(fd1, 1);   OPEN_FILE(fd2, 2);      其展開的等價代碼如下: [cpp]   { fd1 = open(DEV_FILE_NAME1, 0); if (fd1 < 0) { printf("Open device error/n"); return 0; } };   { fd2 = open(DEV_FILE_NAME2, 0); if (fd2 < 0) { printf("Open device error/n"); return 0; } };          值得注意的是,##擴展符是用來連接兩個標簽,但是這兩個標簽之一不能為空!        但是使用這兩個擴展符,有一個極容易出現錯誤的地方,那就是宏展開的問題,且看下面這個例子: [cpp]   #define xstr(s) str(s)   #define str(s) #s   #define foo 4      str(foo); //->”foo”   xstr(foo); //->xstr(4)->str(4)->”4”          為什麼str(foo)與xstr(foo)展開之後會出現完全不同的結果呢?此處就涉及到宏展開的規則問題:在宏預掃描((macro prescan)階段,宏參數首先會被替換,替換之後,再經過下次的掃描完成最後宏的展開(macro expand),OK,說到此,似乎str(foo)在預掃描階段應該會變成str(4),但是GCC在宏預處理階段,特意加上了一條排外規則,那就是若宏參數被用於字符串化或者與其它標簽連接,則不會被替代!結果也就可想而知了。下面是摘抄的一段預處理規則:     Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringified or pasted with other tokens. After substitution, the en-tire macrobody, including the substituted arguments, is scanned again for macros to be expanded.  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved