日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

關(guān)于C語言中的預處理器的簡單筆記

 rookie 2013-02-28

    在將源代碼提交給編譯器之前,C語言預處理器將對源代碼做出一定修正。預處理器命令有很多如最常用的#include,#define命令.

預處理命令都是以#開頭,一般放在代碼的最左側(cè),通常定義的宏全部都是用大寫。

條件編譯

下面這一系列的指令都可以用來決定代碼的哪個部分應該被編譯,這些指令包括:#if,#elif,#else,#ifdef,#else,#ifdef以及#ifndef。以#if開頭的語句塊必須以#endif結(jié)尾。

可以使用條件編譯來注釋代碼,例如


  1. #if 0 
  2.  
  3. /* comment ... 
  4.  
  5. */ 
  6.  
  7.   
  8.  
  9. // code 
  10.  
  11.   
  12.  
  13. /* comment */ 
  14.  
  15. #endif 

#if 表達式,如果表達式為假,那么這部分代碼就不會被編譯,為真才參與編譯。雖然你會說使用塊注釋也是可行的,但是可惜的是塊注視不支持嵌套,在某些環(huán)境下選擇#if 0確實是一個更好的選擇。測試代碼:

 

  1. #include<stdio.h> 
  2.  
  3. int main() 
  4.  
  5.  
  6. #if 0 
  7.  
  8.       int a=10; 
  9.  
  10. #endif 
  11.  
  12.   
  13.  
  14. #if 1 
  15.  
  16.       int a=11; 
  17.  
  18. #endif 
  19.  
  20.       printf("a=%d\n",a); 
  21.  

可以好似用#ifndef來避免頭文件被重復編譯:例如下面這段代碼:


  1. #ifndef _FILE_NAME_H_ 
  2. #define _FILE_NAME_H_ 
  3.   
  4. /* code */ 
  5.   
  6. #endif // #ifndef _FILE_NAME_H_ 

同樣的技術(shù)可以用來定義一些常量,如:


  1. #ifndef NULL 
  2. #define NULL (void *)0 
  3. #endif // #ifndef NULL 

 

宏定義

使用簡單的宏就不多說了,對于比較復雜的宏,常見的是使用類似于函數(shù)定義的宏,使用這種宏要特別注意宏的副作用。例如下面這段代碼:

#define MULT(x, y) x * y
int z = MULT(3 + 2, 4 + 2);

一般情況,要對所有的實參添加括號,同時對宏體整體添加括號。

下面考察一種更加復雜的情況,交換兩個數(shù)的宏定義可以寫為:


  1. #define SWAP(a, b)  a ^= b; b ^= a; a ^= b;  
  2. int x = 10; 
  3. int y = 5; 
  4.   
  5. // works OK 
  6. SWAP(x, y); 
  7.   
  8. // What happens now? 
  9. if(x < 0) 
  10.     SWAP(x, y); 
 

對于第if語句會出現(xiàn)邏輯錯誤,因為這個if語句只執(zhí)行第一個異或操作。嗯,或許你已經(jīng)想到了,加上大括號,像下面這樣:


  1. #define SWAP(a, b)  {a ^= b; b ^= a; a ^= b;}  

然而,還是對于第二個if語句還是不正確,因為預處理器替換之后就出現(xiàn)了‘};’語法錯誤。這里有一個技巧,正確的寫法如下:


  1. #define SWAP(a, b)  do { a ^= b; b ^= a; a ^= b; } while ( 0 ) 

這下就可以了,這里沒有給實參加括號的原因是因為我們只是針對變量的交換,不考慮那些表達式交換。

 

使用\分割宏體

 

如果宏體比較復雜的話,我們就需要使用\來分割宏體,示例代碼如下所示:


  1. #define SWAP(a, b)  {                   \ 
  2.                         a ^= b;         \ 
  3.                         b ^= a;         \  
  4.                         a ^= b;         \ 
  5.                     }  

 

表達式合并

有時候在宏體中我們需要連接兩個參數(shù)的名字這時候可以使用##


  1. struct command 
  2. char *name; 
  3. void (*function) (); 
  4. }; 
  5. struct command commands[] = 
  6. "quit", quit_command}, 
  7. "help", help_command}, 
  8. {"run",run_help}, 
  9. {"open",open_help} 
  10. }; 

struct中顯然每個名字都重復了一遍,通過使用##可以減少重復,方便維護:


  1. #define COMMAND(NAME) { #NAME, NAME ## _command } 
  2. struct command commands[] = 
  3. COMMAND (quit), 
  4. COMMAND (help), 
  5. COMMAND (run), 
  6. COMMAND (open) 
  7. }; 

符號字符串化

有時候我們經(jīng)常需要將傳入到宏中的符號或者叫做參數(shù)轉(zhuǎn)換為文本形式,這樣對于打印這些符號的時候比較方便,在寫一些調(diào)試模塊的時候,經(jīng)常會遇到這樣的需求,實現(xiàn)這個過程的語法很簡單,只需要在符號前面添加一個‘#’就可以了。例如下面這段代碼:


  1. #define PRINT_TOKEN(token) printf(#token " is %d", token) 
  2. PRINT_TOKEN(foo); 

PRINT_TOKEN(foo);將被擴展 printf("<foo>" " is %d" <foo>)

新版本的C語言支持將多個使用雙引號括起來的字符串練成一個整體的字符串。

下面為測試代碼:

 

  1. #include<stdio.h> 
  2.  
  3. #define PRINT_TOKEN(token) printf(#token " is %d\n",token); 
  4.  
  5. int main() 
  6.  
  7.  
  8.       int x=10,y=20; 
  9.  
  10.       PRINT_TOKEN(x+y); 
  11.  

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多