回憶 define的用法

2022-09-15 07:24:15 字數 2900 閱讀 9698

ansi c規定:#前可以有空格或者tab,#和指令其餘部分之間也可以有空格,可以出現在任何地方,作用域從定義處到檔案結尾。

因為預處理開始前,系統會刪除反斜線和換行符的組合,故可以把指令擴充套件到幾個物理行,這些物理行組成單個邏輯行。

//

每個#define行(指邏輯的行):三部分組成

//指令本身 巨集 替換列表(或主體)

#define pi 3.141592653

巨集分為類物件巨集(代表值的巨集)和類函式巨集

巨集的名字中間不能有空格,必須遵循c命名規則,從巨集變成最終的替換文字叫巨集展開,預處理器不進行計算,只是簡單的文字替換

語言符號型別字串和字元型字串

系統把主體當作語言符號型別字串,而不是字元型字串,預處理器中的語言符號是巨集定義主體裡的單獨的詞,用空白字元把這些詞分開。

#define six 2*2//

定義裡有乙個語言符號,序列2*2

#define aaa 2 * 2//

定義裡有三個語言符號,2,*,3

若把主體解釋為字元型字串,預處理器用2    *     2替換aaa,額外的空格也算替換

若把主體解釋為語言符號型別字串,預處理器只用單個空白字元分割的三個語言符號去去替換aaa

2 * 2的空格只是分割主體語言符號的符號,不會都算(注意:不同編譯器做法不一樣)

重定義常量

開始把aaa定義為常量4,後來在該檔案裡,又把aaa定義為10,這叫重定義常量,不同編譯器策略不一樣,不過標準c規定:這是錯誤的,只允許新定義和舊定義完全相同!

//

相同定義意味主體具有相同順序的語言符號

#define a 2 * 3

#define a 2 * 3//

兩者等價,都是三個語言符號的主體

下面的定義被ansi c認為不同

#define a 2*3//

只有乙個語言符號的主體,可以用#undef指令重新定義巨集

在#define裡使用引數——類函式巨集類函式巨集:外形和作用和函式類似,可以使用引數,也是()括起來。一般要主體引數裡都加上小括號來避免文字替換的錯誤發生。

#define  sqrt(x)  x*x

int main(void

)

巨集裡的#和##運算子

#include #include 

#define psqr(x) printf("x的平方 = %d\n", ((x) * (x)));//

注意這裡的;是printf語句的分號

int main(void

)

結果是 x 的平方 = 9

注意,printf引號裡的x被看作是普通的文字,而不是乙個可以被替換的語言符號!可以在類函式巨集的替換部分,使用#運算子做預處理,這樣普通文字轉換為可以被替換的語言符號!如果x是巨集引數,那麼#x可以把引數名轉換為相應的字串處理,就可以輸出3,而不是x!(該過程也叫字串化)。

#define psqr(x) printf(#x "的平方 = %d\n", ((x) * (x)));

int main(void

)

3的平方 = 9

呼叫巨集,用 」3」 代替 #x ,標準c把這些字串鏈結起來,產生最終結果。

#只可以用於類函式巨集,而##運算子既可以用於類函式巨集,也可以用到類物件巨集。

##可以把兩個語言符號組合為單個語言符號!

#define xname(n) x##n //類函式巨集裡,n是巨集引數(乙個語言符號),x是乙個語言符號,加上##,兩者變乙個語言符號

#define print_xn(n) printf("x" #n " = %d \n", x ## n);//注意這裡x必須大寫,因為xname裡x大寫了

int main(void)

列印 x1 = 14

可變巨集

函式可以接收固定引數,也可以接收可變引數(printf函式)。同樣巨集也是這樣。

注意:可變,字串化是c的詞彙,但是固定函式,固定巨集,不變巨集等不是c的詞彙。

實現思想:巨集定義的引數列表最後乙個引數為省略號…(三個點),預定義巨集__va_args__就可以用在被替換部分,說明省略號的含義。

#include #include 

#include

#define pr(x, ...) printf("可變巨集:" #x __va_args__ );//

注意這裡是兩個下劃線__

int main(void

)

巨集是用空間換取時間,函式是用時間換取空間,比如,使用巨集100次,那麼會在程式裡插入100次巨集代表的**,浪費空間,但是速度很快。使用函式100次,程式只有乙份函式的拷貝,節省空間,但是每次呼叫函式,都要壓棧出棧,返**用點,浪費時間!

簡單函式就能處理的功能,一般用巨集,或者內聯函式。

巨集名字不能有空格,必須大寫(約定俗成的,提醒程式設計師這是巨集),巨集不檢測型別只是簡單的文字替換,好處是int型別,或者double型別等都能使用。

用圓括號括起來類函式巨集裡的每個引數,好習慣,避免文字替換造成邏輯混亂的錯誤。

dashuai的部落格是終身學習踐行者,大廠程式設計師,且專注於工作經驗、學習筆記的分享和日常吐槽,包括但不限於網際網路行業,附帶分享一些pdf電子書,資料,幫忙內推,歡迎拍磚!

define巨集的用法

再舉乙個使用無引數巨集替代字串的例子 define m y y 3 y include int main define m y y 3 y 定義m表示式 y y 3 y 在編寫源程式時,所有的 y y 3 y 都可由m代替,而對源程式作編譯時,將先由預處理程式進行巨集代換,即用 y y 3 y 表示...

define 的高階用法

原文 一 linux c中用define定義可變引數的巨集 一般在除錯列印debug資訊的時候,需要可變引數的巨集.從c99開始可以使編譯器標準支援可變引數巨集 variadic macros 另外gcc也支援可變引數巨集,但是兩種在細節上可能存在區別.1.va args va args 將 傳遞給...

define 特殊用法

define conn x,y x y define tochar x x define tostring x x x y表示什麼?表示x連線y,舉例說 int n conn 123,456 結果就是n 123456 char str conn asdf adf 結果就是 str asdfadf 再...