預處理 老大巨集定義和使用技巧

2021-07-24 07:48:57 字數 3422 閱讀 7631

所謂預處理是指在進行編譯的第一遍掃瞄(詞法掃瞄和語法分析)之前所做的工作。預處理是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 使用...