C語言 巨集定義,預處理巨集

2021-09-27 11:16:07 字數 4540 閱讀 9828

巨集是學習任何語言所不可缺少的,優秀的巨集定義可以使得**變得很簡潔且高效,有效地提高程式設計效率。

巨集是一種預處理指令,它提供了一種機制,可以用來替換源**中的字串,直譯器或編譯器在遇到巨集時會自動進行這一模式替換

c語言有簡單的巨集系統,由編譯器或彙編器的預處理器實現。c的巨集預處理器的工作只是簡單的文字搜尋和替換,

c語言的巨集非常簡單,我們只需要做好巨集定義,其餘交給編譯器預處理即可

1. 巨集定義

2. 包含標頭檔案的巨集

3. 條件編譯巨集

4. 預定義巨集

c程式提供的預處理功能之一。包括帶引數的巨集定義和不帶引數的巨集定義。具體是指用乙個指定的標誌符來進行簡單的字串替換或者進行闡述替換。形式為:

#define  標誌符[(參數列)] 字串
其中「#」表示這是一條預處理命令(在 c 語言中凡是以「#」開頭的均為預處理命令)「define」為巨集定義命令,「識別符號」為所定義的巨集名, 「字串」可以是常數、表示式、格式串等。符號常量的定義就是一種無參巨集定義

常見使用

//巨集定義

#define size 1000

//取消巨集

#undef size

//普通巨集

#define pi 3.1415926

//帶引數的巨集

#define max(a,b) ((a)>(b)? (a),(b))

其實巨集定義就是乙個簡單的字串替換,將前面的字串替換成後面的字串。

當然要注意,#define巨集定義的作用僅僅是替換,它只是乙個簡單的替換,

比如下方**:

#define   m(a,b)  a*3+b*4

c =m(5

+6,2

+4)//c的結果等於41

這裡的巨集定義僅僅是將a換為5+6 而不是11 將b換位2+4 而不是6

因此順序應該是 5+63+2+44 = 41

如果想要實際的預期結果 則需要

#define   m(a,b)  a*3+b*4

c =m((

5+6)

,(2+

4))//應該使用括號將其包圍

//c的結果等於57

再比如

#define point (int*);

point a,b;

本意是a和b都是int型指標,但是實際上變成int* a,b;

a是int型指標,而b是int型變數。

這點要尤為注意

巨集連線:

c語言中,使用兩個#即可將兩個字元連線成為乙個

#include

#define a1 printf("print a1\r\n")

#define a2 printf("print a2\r\n")

#define a(name) a##name

intmain()

會列印:

print a1
在該例子中,呼叫巨集a(1)時,name為1。a##name這個符號連線,即將a和1連線成了乙個符號a1,然後執行巨集a1的內容。最終列印出來了print a1

還有就是

無法通過巨集展開的方式建立預處理器命令。即使巨集的展開結果會生成形式上有效的命令,但預處理器不會執行它

你所要知道的小知識:

定義巨集不占用記憶體,只有在使用時才分配記憶體

巨集定義不存在型別問題,它的引數也是無型別的

字串" "中不能使用巨集定義預處理是在編譯之前的處理,而編譯工作的任務之一就是語法檢查,預處理不做語法檢查

巨集替換在預處理階段進行,函式呼叫在編譯後程式執行時進行,並且分配記憶體。預處理在編譯之前,因此巨集替換不分配記憶體

巨集定義前面的替換必須是c語言合法的使用者識別符號如 #define 0a 25 就是錯誤的

重複定義的巨集只有最後乙個是有效的巨集定義不是c語句,不必在行未加「;」號,如果加了連「;」號一起進行置換;

用乙個include表示,引入的標頭檔案有兩種區別

一種是c語言自帶的標頭檔案,用<>來表示

#include

編譯的時候會在編譯器的bin目錄下面查詢

另一種是使用者自定義標頭檔案,用""來表示

#include

"led.h"

編譯時從對應自定義檔案路徑查詢

當然 ,c語言自帶標頭檔案也可以使用""這個我們講解下:

也就是說使用雙引號比使用尖括號多了乙個查詢路徑

#include 引入標頭檔案的本質就是原始碼替換,預處理的時候將那些.**件中的**替換到頭檔案引入的位置進行編譯 比如printf就會從stdio.h中尋找對應原始碼,之後進行替換,再替換以後的結果再交給編譯器處理,進行編譯。

c語言中條件編譯相關的預編譯指令

#define            定義乙個預處理巨集

#undef 取消巨集的定義

#if 編譯預處理中的條件命令,相當於c語法中的if語句

#ifdef 判斷某個巨集是否被定義,若已定義,執行隨後的語句

#ifndef 與#ifdef相反,判斷某個巨集是否未被定義

#elif 若#if, #ifdef, #ifndef或前面的#elif條件不滿足,則執行#elif之後的語句,相當於c語法中的else-if

#else 與#if, #ifdef, #ifndef對應, 若這些條件不滿足,則執行#else之後的語句,相當於c語法中的else

#endif #if, #ifdef, #ifndef這些條件命令的結束標誌.

defined  與#if

, #elif配合使用,判斷某個巨集是否被定義

#error 編譯程式時如果遇到#error就會生成乙個編譯錯誤提示資訊並停止編譯

舉個簡單的例子:

#define  zzx

#ifdef zzx

printf

("定義了z小旋");

#else

printf

("沒有定義z小旋");

#endif

上面的**就會輸出定義z小旋 而不滿足條件的**就不會編譯

我們經常使用條件編譯來定義標頭檔案

#ifndef _datacollect_h_

#define _datacollect_h_

#**塊

#endif

條件編譯再我們正常程式的編寫中是非常見的,你可以使用條件編譯完成模組不同功能的設定,比如你想要用一套**編譯乙個產品的兩個功能,使用條件編譯,乙個#ifndef 即可完成兩個不同**塊的切換,決定編譯的時候生成的是哪個功能的**。

巨集名稱功能

_line_

正在編譯的檔案的行號

_file_

正在編譯的檔案的名字

_date_

編譯時刻的日期字串

_time_

編譯時刻的時間字串

_stdc_

判斷該程式是否為標準的c程式

標準的預定義巨集都是用一兩個下劃線字元開頭和結尾,這類巨集不能被#undef所取消也不能被程式設計人員重新定義和修改,常用來說明檔案資訊等

#include

intmain()

輸出如下:

date : sep 28

2019

time :21:

46:50file : c:\users\48013\desktop\小學弟的渣渣c\預定義巨集.c

line :

6

剩餘部分巨集:

巨集名稱功能

_stdc_version_

表示iso c的版本

_stdc_hosted_

如果值為1的話,表示目標環境有完成的標準c庫

_byte_order_

表示當前環境的位元組序

_lp64_

表示當前環境是不是64位,如果該值為1,則環境為64位環境

c語言預處理 巨集定義

個人筆記 巨集定義對於用c語言程式設計的人是經常用,這裡只講使用中需注意的問題點和方便的用法。1.巨集擴充套件中空格對擴充套件結果的影響 define a y a expanded y a x 被擴充套件為 a expanded x define a y a expanded y a x 被擴充套件...

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 使用...