所謂預處理是指在進行編譯的第一遍掃瞄(詞法掃瞄和語法分析)之前所做的工作。預處理是c語言的乙個重要功能,它由預處理程式負責完成的。對當乙個原始檔進行編譯時,系統將自動引用預處理程式中的預處理部分進行處理,處理完畢自動進入對源程式的編譯。
c語言提供了多種預處理功能,如巨集定義、檔案包含、條件編譯等,合理地使用預處理功能編寫的程式便於閱讀、修改、移植和除錯,也有利於模組程式設計。
巨集定義是由源程式中的巨集定義命令完成的。巨集代換是由預處理程式自動完成的,在c語言中,巨集分為有引數和無引數兩種。
1、無參巨集定義
無參巨集的巨集名後不帶引數,其定義的一般形式為
#define 識別符號 字串
#表示這是一條預處理命令,凡是以#開頭的均為預處理命令;define為巨集定義命令;識別符號為所定義巨集名;字串可以是常數、表示式、格式串等。
常對程式中反覆使用的表示式進行巨集定義。
說明:1)巨集定義是用巨集名來表示乙個字串,在巨集展開時又以該字串取代巨集名。
2)巨集定義不是說明語句,在行末不必加分號,如加上分號則連分號也一起置換。
3)巨集定義必須寫在函式外,其作用域為巨集定義命令起到源程式結束。如要終止其作用域可使用」#undef「命令
2、帶參巨集定義
在巨集定義中的引數稱為形式引數,在巨集呼叫中的引數稱為實際引數。對帶引數的巨集,在呼叫中,不僅要巨集展開,而且要用實參去代換形參。一般形式為:
#define 巨集名(形參表) 字串
在字串中含有各個形參。帶參巨集呼叫的一般形式為
巨集名(實參表);
帶參巨集定義與自定義函式的區別
1)帶參巨集定義中,形式引數不分配記憶體單元 ,因此不必做型別定義;而巨集呼叫中的實參有具體的值,要用它們去代換形參,因此必須作型別說明。這與函式中的情況是不同的,在函式中,形參和實參是兩個不同的量,各有自己的作用域,呼叫時要把實參值賦予形參,進行」值傳遞「。而在帶參巨集中,只是符號代換,不存在值傳遞的問題。
2)在巨集定義中的形參是識別符號,而巨集呼叫中的實參可以是表示式。
注意:在巨集定義中,字串內的形參通常要用括號括起來以避免出錯。
寫好c語言,漂亮的巨集定義很重要,使用巨集定義可以防止出錯,提高可移植性、可讀性、方便性等。
1、防止乙個標頭檔案被重複包含
#ifndef comdef_h
#define comdef_h
//標頭檔案內容
#endif
2、得到指定位址上的乙個位元組或字
#define mem_b (x) (*( (byte *) (x) ) )
#define mem_w (x) (*( (word *) (x) ) )
3、求最大值和最小值
#define max (x,y) ( ( (x) > (y) ) ? (x) : (y) )
#define min (x,y) ( ( (x) > (y) ) ? (x) : (y) )
4、得到乙個field在結構體(struct)中的偏移量
#define fpos (type,field) \
/*lint -e545 */ ( (dword) & ( ( type *) 0)->field) /*lint +e545*/
5、得到乙個結構體中field所占用的位元組數
#define fsiz( type,field ) sizeof ( ( ( type *) 0)->field )
6、按照lsb格式把兩個位元組轉化為乙個word
#define flipw( ray ) ( ( ( ( word) (ray)[0] ) *256 ) + (ray)[1] )
7、按照lsb格式把乙個word轉化為兩個位元組
#define flopw (ray,val ) \(ray)[0] = ( (val) /256 );\
(ray)[1] = ( (val) & 0xff)
8、得到乙個變數的位址 (word寬度)
#define b_ptr( var ) ( (byte *) (void *) &(var) )
#define w_ptr( var ) ( (word *) (void * ) & (var) )
9、得到乙個字的高位和低位位元組
#define word_lo(***) ( (byte) ( (word) (***) & 255 ) )
#define word_hi(***) ( (byte) ( (word) (***) >> 8 ) )
10、防止溢位的乙個方法
#define inc_sat(val) (val = ( (val)+1 > (val) ) ? (val) + 1:(val) )
11、對於io空間對映在儲存空間的結構,輸入輸出處理
#define inp(port) (*( (volatile byte * ) (port) ) )
#define inpw(port) (*( (volatile word * ) (port) ) )
#define inpdw(port) (*( (volatile dword * ) (port) ) )
#define outp (port,val) (*( (volatile byte * ) (port) ) = ( (byte) (val) ) )
#define outpw (port,val) (*( (volatile word * ) (port) ) = ( (word) (val) ) )
12、使用一些巨集跟蹤除錯
ansi標準說明了五個預定義的巨集名,他們分別是_line_、_file_、_date_、_time_、_stdc_。如果編譯不是標準的,則可能僅支援以上巨集名中的幾個,或根本不支援,記住編譯程式也許還提供其他預定義的巨集名。
_line_及_file_巨集指令列印所在行數和函式名。_date_巨集指令含有形式為月/日/年的串,表示原始檔被翻譯到**時的日期。源**翻譯到目標**的時間作為串包含在_time_中,串形式為「時:分:秒」。如果實現是標準的,則巨集_stdc_含有十進位制常量1;如果它含有任何其他數,則實現是非標準的。可以定義巨集,例如,當定義了_debug,輸出資料資訊和所在檔案所在行
#ifdef _debug
#define debugmsg(msg,date) printf(msg);
printf ("%d%d%d",date,_line_,_file_)
#else
#define debugmsg(msg,date)
#endif
預處理 巨集定義
1,預處理 預處理是指在進行編譯的第一遍掃瞄 詞法掃瞄和語法分析 之前所作的工作。預處理是 語言的乙個重要功能,它由預處理程式負責完成。當對乙個原始檔進行編譯時,系統將自動引用預處理程式對源程式中的預處理部分作處理,處理完畢自動進入對源程式的編譯。語言提供了多種預處理功能,如巨集定義 檔案包含 條件...
C 預處理 巨集定義
開發乙個 c語言程式,讓它暫停 5 秒以後再輸出內容 helllo 並且要求跨平台,在 windows 和 linux 下 include 說明 在windows 作業系統和 linux作業系統下,生成原始碼不一樣 if win32 如果是windows平台,就執行 include elif lin...
C語言 預處理和巨集定義
今天分享一點c語言的預處理還有巨集相關的內容。目錄 預處理和巨集定義 一 乙個c程式的誕生 1 預編譯階段 c i 2 編譯階段 i s 3 彙編階段 s o 4 鏈結階段 該程式的所有.o exe 1 c語言中部分內建巨集 2 巨集的功能 1 使用巨集定義常量 2 使用巨集重新命名運算子 3 使用...