1 不帶參宏定義
這種用法是最簡單最常見的一種方式,如下:
#define PAI 3.14
注意:
- 宏定義原則上用大寫表示,雖然這並不是規定
- 由於宏定義是預處理指令,並非是C語言語句,所以末尾不必加分號
它的功能是在程序中若出現了PAI
,就把它替換爲3.14
,示例程序如下:
#include <stdio.h>
#define PAI 3.14 // 不帶參宏定義
int main() {
double r = 2;
printf("半徑爲%.2lf的圓的周長爲%.2lf", r, 2*PAI*r);
return 0;
}
2 帶參宏定義
使用方法如下:
#define ADD(a,b) (a+b)
它的功能是計算a+b
的結果,示例程序如下:
#include <stdio.h>
#define ADD(a,b) (a+b)
int main() {
int a = 1;
int b = 2;
printf("a+b=%d", ADD(a, b));
return 0;
}
這裏需要注意的是,我們習慣上會把後面表達式添上括號,如(a+b)
,在本例中去掉這個括號也是可以的,但有些情況下會出現問題,如下:
#include <stdio.h>
#define ADD(a,b) a+b
#define SUB(a,b) a-b
int main() {
int a = 1;
int b = 2;
printf("%d", ADD(a,b)*SUB(a,b)); // ab的和與差相乘
return 0;
}
這個程序的功能是計算a+b
乘以a-b
的值,實際上程序的輸出結果爲1
,我們稍加思考發現本例中a+b>0
,a-b<0
答案必然是負數,結果卻是正數,顯然出了問題,那麼再把表達式的括號加上試試看:
#define ADD(a,b) (a+b)
#define SUB(a,b) (a-b)
程序運行後輸出結果爲-3
,可以口算發現此結果是正確的,出現問題的原因就要從#define
預編譯指令的原理說起,在編譯一個C語言程序時,第一步執行的是預編譯這個過程中會把#define
中定義的宏進行替換,如不加括號的程序中就替換成了如下:
printf("%d", a+b*a-b); // 輸出結果爲1
顯然根據數學運算規則會先算乘法後算加法,所以結果爲1
,那麼加上括號的程序中替換後結果如下:
printf("%d", (1+2)*(1-2)); // 輸出結果爲-3
先算括號裏的式子,整個式子的結果顯然爲-3
,通過本例可以發現爲了避免替換後出現類似這種錯誤,儘量將表達式加上括號,特別是表達式中有多個變量時
帶參宏定義和函數有點像,他們的區別如下:
- 函數參數傳遞時會計算實參的值再傳遞給形參,如執行函數
func(1+2)
,會先計算1+2
的值爲3
再交給函數體,而帶參宏定義不進行任何計算,直接替換- 根據上面例子可以發現,帶參宏定義對數據類型沒有定義,可以使用多種合法類型帶入,但函數要根據定義函數時聲明的參數類型傳遞值
- 帶參宏定義僅佔用預編譯的時間,而函數的執行會佔用空間和時間,如分配內存空間,入棧保留現場,返回值等
3 與字符串有關的用法
3.1 字符串轉換
使用方法如下,在s
前加上#
,它的作用是將傳入的s
轉換爲字符串
#define STR(s) #s
示例程序如下,給出參數Wuhan jia you
,最後以字符串的形式輸出來
#include <stdio.h>
#define STR(s) #s
int main() {
puts(STR(Wuhan jia you));
return 0;
}
需要注意的是,轉換的是s
,而不是s
裏的值,見下面兩個程序:
// 程序1
#include <stdio.h>
#define STR(s) #s
int main() {
const char *s = "Wuhan jia you";
puts(STR(s));
return 0;
}
// 程序2
#include <stdio.h>
#define STR(s) #s
int main() {
int n = 2020;
puts(STR(n));
return 0;
}
第一個程序輸出結果爲s
,第二個程序的輸出結果爲n
,可見這個用法就是你給它什麼,它就把它直接轉換爲字符串,不管它是不是變量
3.2 字符轉換
使用方法如下,在c
的前面加上#@
,它的作用是把c
轉換爲字符
#define STR(c) #@c
注意:本用法不支持gcc編譯器,如在gcc編譯器下編譯,會出現下面的錯誤信息
error: '#' is not followed by a macro parameter
,這個用法僅支持微軟系列(Microsoft Specific)
示例程序如下,給出參數1
,最後把1
轉換爲字符1
輸出:
#include <stdio.h>
#define STR(c) #@c
int main() {
putchar(STR(1));
return 0;
}
關於它的轉換規則和3.1 字符串轉換
的類似
3.3 字符連接
使用方法如下,在兩個參數中間添加##
,它的作用是連接前後兩個參數,把它們變成一個參數
#define CAT(a,b) a##b
示例程序如下
#include <stdio.h>
#define CAT(a,b) a##b
int main() {
int n = CAT(123, 456);
printf("%d", n);
return 0;
}
輸出結果爲123456