宏定義 #define
宏定義能夠在代碼中直接替換相關的內容,恰當地使用可以提高程序的執行效率,提高程序的清晰度和可讀性,提供了一種複用方式(否則都得用函數編寫),省去了分配和釋放棧幀、傳參、傳返回值等一系列工作, 但是大量使用也會造成代碼可讀性下降。
常用宏定義命令
命令 | 解釋 |
---|---|
define | 定義一個預處理宏 |
undef | 取消宏的定義 |
include | 包含文件命令 |
include_next | 與#include相似, 但它有着特殊的用途 |
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配合使用, 判斷某個宏是否被定義 |
line | 標誌該語句所在的行號 |
“#” | 將宏參數替代爲以參數值爲內容的字符竄常量 |
“##” | 將兩個相鄰的標記(token)連接爲一個單獨的標記 |
pragma | 說明編譯器信息 |
warning | 顯示編譯警告信息 |
error | 顯示編譯錯誤信息 |
其中 ## 表示連接兩個字符, # 表示將參數字符串化
不帶參宏定義
例如: #define MAX 1000
(1)宏名一般用大寫
(2)使用宏可提高程序的通用性和易讀性,減少不一致性,減少輸入錯誤和便於修改。例如:數組大小常用宏定義
(3)預處理是在編譯之前的處理,而編譯工作的任務之一就是語法檢查,預處理不做語法檢查。
(4)宏定義末尾不加分號;
(5)宏定義寫在函數的花括號外邊,作用域爲其後的程序,通常在文件的最開頭。
(6)可以用#undef命令終止宏定義的作用域
(7)宏定義可以嵌套
(8)字符串" "中永遠不包含宏
帶參的宏定義
例如:#define ADD(x,y) ((x)+(y))
1)實參如果是表達式容易出問題
#define S(r) r*r
area=S(a+b);第一步換爲area=r*r;,第二步被換爲area=a+b*a+b;
正確的宏定義是#define S(r) (r)*(r)
(2)宏名和參數的括號間不能有空格
(3)宏替換隻作替換,不做計算,不做表達式求解
(4)函數調用在編譯後程序運行時進行,並且分配內存。宏替換在編譯前進行,不分配內存
(5)宏的啞實結合不存在類型,也沒有類型轉換。
(6)函數只有一個返回值,利用宏則可以設法得到多個值
(7)宏展開使源程序變長,函數調用不會
(8)宏展開不佔運行時間,只佔編譯時間,函數調用佔運行時間(分配內存、保留現場、值傳遞、返回值)
(9)宏定義不分配內存,變量定義分配內存。宏替換髮生的過程
宏函數
//此函數會一直打印 “hello”
#include<stdio.h>
#define FOO(str)printf("%s",str);
#define FUN1(i)do{printf("hello");}while (i)
#define FUN2(i)for (;i;){printf("hello");}
int main(void)
{
FOO("hello");
if (3)
{
FUN2(2)
}
else
FUN1(0);
getchar();
return 0;
}
#pragma
去除4127號警告 #pragma warning(disable:4127)
使用示例
#define forEachAs( listtype, list, iter ) \
for ( listtype::iterator iter = (list)->begin(); iter != (list)->end(); ++iter )
#define ADD(a,b) (a+b)