巨集定義筆記

2021-08-01 05:15:36 字數 4456 閱讀 4521

巨集定義有兩種:簡單巨集定義,帶引數的巨集定義。

簡單巨集定義:#define 識別符號 替換列表

#define為常量命名的優點:

1. 程式會更易讀;

2. 程式更易於修改;

3. 可以幫助避免前後不一致或鍵盤輸入錯誤;

其他應用:

1. 可以對c語法做小的修改:

#define begin   

// 之間的空格符是可以任意的

甚至可以定義:#define loop for( ;; )

2.對型別重新命名:#define bool int

但是,通常使用typedef 對型別重新命名

3.控制條件編譯:

帶引數的巨集定義#define 識別符號(x1,x2,x3,...,xn) 替換列表

如:

#define max(x,y) ((x)>(y) ? (x) :(y))

//替換列表中的引數都使用()括起來,可避免之間優先順序不同而出錯

可以包含空的引數列表:#define getchar() getc(stdin)

優點:

程式可能會稍微快些。乙個函式呼叫在執行時通常有些額外開銷—–儲存上下文資訊,複製引數的值等。而巨集的呼叫沒有。

巨集會更」通用」。與函式的引數不同,巨集的引數型別沒有型別。因此,只要預處理後的程式合法,巨集可以接收任何型別的引數。

缺點:

編譯後**通常會增加。

巨集引數沒有型別檢查。預處理器不會檢查巨集引數型別,也不會進行型別轉換

無法用乙個指標來指向乙個巨集。巨集在預處理的過程中被刪除,所以不存在類似的「指向巨集的指標」。

巨集可能會不止一次地計算它的引數。如果引數有附加作用,多次計算引數的值可能會產生意外的結果。例如:

n = max(i++,j);

n = ((i++)>(j)?(i++):(j));

如果i>j, 那麼i可能會被計算兩次,結果n被賦錯誤值。

因此,為避免這種情況,最好不使用帶有附加作用的引數。

將乙個巨集的引數轉換為字串字量。它僅允許出現在帶引數的巨集的替換列表中。

例如:

#define print_int(x) printf(#x " = %d\n", x)

x之前的#通知預處理器根據 print_int 的引數建立乙個字串字面量。因此,呼叫print_int(i/j);會變成printf("i/j"" = %d\n",i/j);等價於printf("i/j = %d\n",i/j);

##運算子可以將兩個記號連在一起,成為乙個記號。例如,#define mk_id(n) i##n

int mk_id(1),mk_id(2),mk_id(3);等價於int i1,i2,i3;

##用於同一功能,不同資料型別的函式的巨集定義,如:

#define generic_max(type)         \

type

type##_max(

type

x, type

y) \

generic_max(float)等價於float float_max(float x,float y)

在建立較長的巨集時, 逗號號運算子很有用。可以用逗號運算子使替換列表包含一系列表示式,如:

#define echo(s) (gets(s), puts(s))

而,如果想在巨集的替換列表中包含一系列語句,可以用dowhile(0),如:

#define echo(s)     \

do while(0)

注意:在使用echo巨集時,一定要加分號:echo(str);

名字描述

_line_被編譯檔案行數

_file_被編譯檔案名字

_date_編譯的日期(m d y)

_time_編譯時間(h:m:s)

_stdc_如果編譯器接受標準c,那麼值為1

printf("linux (c) 2017 king software,inc.\n");

printf("complied on %s at %s\n, _date_, _time_");

程式開始執行,都會列印編譯的日期和時間,可以用來區分同一程式的不同版本。

_line__file_可以用來找錯誤。當乙個c程式因為被0除(或被0餘)而導致終止時,通常沒有資訊指明哪條除法(或余)導致錯誤。下面的巨集可以幫助查明錯誤的根源:

#define check_zero(divisor)  \

if(divisor == 0) \

printf("**

*attempt to divide by zero on line %d of file %s

***\n", _line_, _file_);

check_zero巨集應該在(餘)除法運算前被呼叫:

check_zero(j);

k = i/j;

如果j = 0,顯示錯誤位置。

c語言庫提供了乙個通用的、用於錯誤檢測的巨集——assert巨集。

#if & #endif

#define debug 1

#if debug

....

#endif

如果debug設為1,預處理器就將#if 與 #endif 之間的語句保留到程式中,進行編譯;如果debug設為0,預處理器就刪去此段**。

對於沒有定義過的標識,#if 將它視為0

defined運算子

使用:defined 識別符號如果識別符號已經定義為巨集返回1,否則返回0。

#define debug //不需要給定值

#if defined debug

....

#endif

#ifdef & #ifndef

#ifdef //相當於#if defined

#ifndef //相當於#if !defined

#elif & #else

#if 識別符號

#if 表示式1

#elif 條件1

#elif 條件2

....

#else

#endif

elif可以多次使用,else只能在其中使用一次。

使用條件編譯的好處:

編寫多台機器或者多個作業系統的可移植程式。

#if defined windows

....

#elif defined unix

....

#elif defined os

....

#endif

編寫可以使用不同編譯器編譯的程式。

#if _stdc_ //標準c函式原型

....

#else //經典c函式宣告

....

#endif

為巨集提供預設定義。

#ifndef buffer_size

#define buffer_size 256

#endif

臨時遮蔽包含注釋的**。由於在標準c中不能用注釋巢狀

#if 0

包含注釋的**行

#endif

學習筆記 巨集定義基礎

在c c 中,巨集定義是由define完成的。define f a,b a b define g a a define h a g a f 1,2 輸出 12 輸出格式為 d 若為 s則報錯 g f 1,2 輸出 f 1,2 輸出格式 s h f 1,2 輸出 12 輸出格式 s 最外層巨集可替換至...

abs int 巨集定義 巨集定義和巨集方法

巨集定義和巨集方法 定義機型 define is iphone5 uiscreen instancesrespondtoselector selector currentmode cgsizeequaltosize cgsizemake 640,1136 uiscreen mainscreen cu...

預處理與巨集定義 筆記

2017 09 18 10 45 21 預處理1.預處理的指令和功能 以 開頭的語句 include 檔案包含 include 在標準庫下面找 include stdio.h 在當前工作路徑下查詢 自定義標頭檔案的包含形式 區別 查詢的路徑不相同 define 巨集定義 不帶引數的巨集和帶引數的巨集...