深入浅出讲解C语言#define宏定义应用及使用方法
在C語言中,我們使用#define來定義宏。在C程序編譯的預處理階段,預處理器會把宏定義的符號替換成指定的文本。
不帶參數的宏
關于宏最常見的就是用來定義數值常量的名稱,即沒有參數的宏定義,采用如下形式:
1#define?宏名稱????替換文本例如:
1#define?ARRAY_SIZE????10 2int?data[ARRAY_SIZE];當程序需要修改數組長度時,只需要修改宏定義即可,無需對程序中每一處用到數組長度的地方進行修改。
帶參數的宏
你可以定義具有形參的宏,然后預處理器展開這類宏時,會將宏指定的實參替換文本中對應的形參。這有點像函數,故也叫做函數式宏定義、類函數宏,形式如下:
1#define?宏名稱([行參列表])?替換文本 2#define?宏名稱([行參列表,]...)????替換文本當宏被調用時,替換文本中的每個值都與形參列表相對應。另外C99標準允許定義有參略號的宏,省略號必須放在參數列表的后面,以表示可選參數。
當調用有可選參數的宏時,預處理器會將所有可選參數連同分隔它們的逗號打包在一起作為一個參數。在替換文本中,標識符?__VA_ARGS__對應前面打包的可選參數。
1//假設有個已經打開的日志文件,準備采用文件指針fp_log對其進行寫入 2#define?printLog(...)?fprintf(fp_log,?__VA_ARGS__) 3//使用printLog 4printLog("%s:?intVar=%d\r\n",?__func__,?intVar);預處理器把最后一行的宏調用替換成下面一行代碼:
1fprintf(fp_log,?"%s:?intVar=%d\r\n",?__func__,?intVar);帶參宏的一些問題
1#include? 2#define?SQUARE(x)???x?*?x 3int?main(int?argc,?char?const?*argv[]) 4{ 5????int?a?=?5; 6????printf("%d\r\n",?SQUARE(5)); 7????printf("%d\r\n",?SQUARE(a+1)); 8????return?0; 9}程序運行,第一條打印顯而易見為25,第二條打印為多少呢?不是36而是11。我們通過"gcc -E a.c >a.txt",將預處理后的文件重定向到a.txt,來觀察被替換的宏文本。
1printf("%d\r\n",?5?*?5); 2printf("%d\r\n",?a+1?*?a+1);可見替換產生的表達式并沒有按照預想的次序進行求值。可能大家會說,加上兩個括號就解決了嘛:
1#define?SQUARE(x)??(x)?*?(x)那么,為每個出現在替換文本中的參數加上括號就一定沒問題了嗎?看下面例子:
1#include? 2#define?ADD(x)????(x)?+?(x) 3int?main(int?argc,?char?const?*argv[]) 4{ 5????int?a?=?5; 6????printf("%d\r\n",?10?*?ADD(5)); 7????return?0; 8}看似輸出100,實際輸出55。我們看下替換后的文本:
1printf("%d\r\n",?10?*?(5)?+?(5));乘法運算在加法運算之前執行,所以結果為55。這個錯誤很容易修正:整個表達式加上括號:
1#define?ADD(x)????((x)?+?(x))所有對數值表達式進行求值的宏定義,為避免參數中操作符或鄰近的操作符之間不可預料的互相作用,應對每個參數加括號,整個表達式也要加括號。
宏與函數
盡可能多的加括號就絕對不會有問題了嗎?看下面例子:
1#include?2#define?MAX(a,?b)????((a)?>?(b)???(a)?:?(b))3int?main(int?argc,?char?const?*argv[])4{總結
以上是生活随笔為你收集整理的深入浅出讲解C语言#define宏定义应用及使用方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 创新口号8字押韵88句
- 下一篇: iOS 17支持第三方应用商店服务要收费