???個人主頁:?會編輯的果子君
??個人格言:“成為自己未來的主人~”??
目錄
帶有副作用的宏參數(shù)
宏替換的規(guī)則
宏函數(shù)的對比
?#和##
#運算符
##運算符
命名約定
#undef
帶有副作用的宏參數(shù)
當宏參數(shù)在宏的定義中出現(xiàn)超過一次的時候,如果參數(shù)帶有副作用,那么你在使用這個宏的時候就可能出現(xiàn)危險,不可控的后果,副作用就是表達式求值的時候出現(xiàn)的永久性效果
例如:
x + 1;//沒有副作用
x++; //有副作用
MAX宏可以證明具有副作用的參數(shù)所引起的問題:
#define MAX(a,b) ((a)>(b)?(a):(b))
#include<stdio.h>
int main()
{
int x = 5;
int y = 8;
int z = MAX(x++, y++);
printf("%d,%d,%d", x, y, z);
return 0;
}
輸出結果為 6 10 9
宏替換的規(guī)則
在程序中擴展#define定義符號和宏時,需要涉及幾個步驟
- 在調(diào)用宏的時候,首先對參數(shù)進行檢查,看看是否包含任何由#define定義的符號,如果有,他們首先被定義。
- 替換文本隨后被插入到程序原來文本的位置,對于宏,參數(shù)名被他們的值所替換
- 最后,再次對結果文件進行掃描,看看它是否包含任何由#define定義的符號,如果有,就重復上述過程。
注意:
宏參數(shù)和#define定義中可以出現(xiàn)其他#define定義的符號,但是對于宏,不能出現(xiàn)遞歸
當預處理器搜索#define定義的符號的時候,字符串常量的內(nèi)容并不被搜索。
宏函數(shù)的對比
宏通常被應用于執(zhí)行簡單的運算
比如在兩個數(shù)中找到比較大的一個時,寫成下面的宏,更有優(yōu)勢一些。
#define MAX(a,b) ((a)>(b)?(a):(b))
那為什么不用函數(shù)來完成這個任務?
原因有2:
- 用于調(diào)用函數(shù)和從函數(shù)返回的代碼可能比實際執(zhí)行這個小型計算工作所需要的時間更多,所以宏比函數(shù)在程序的規(guī)模和速度方面更勝一籌。
- 更為重要的是函數(shù)的參數(shù)必須聲明為特定的類型,所以函數(shù)只能在類型合適的表達式上使用,反之這個宏可以適用于整型,長整型,浮點型等可以用于>來比較的類型,宏是類型無關的。
和函數(shù)相比宏的劣勢:
- 每次使用宏的時候,一份宏的定義的代碼插入到程序中,除非宏比較短,否則會增加代碼的長度。
- 宏時沒法調(diào)試的
- 宏由于類型無關,所以不夠嚴謹
- 宏可能會帶來運算符優(yōu)先級的問題,導致程序容易出錯
宏有時候可以做函數(shù)做不到的事情,比如,宏的參數(shù)可以出現(xiàn)類型,但是函數(shù)做不到
#define MALLOC(num,type) \
(type*)malloc(num,sizeof(type))
MALLOC(5.int)
?#和##
#運算符
#運算符將宏的一個參數(shù)轉換為字符串字面量,它僅允許出現(xiàn)在帶參數(shù)的宏的替換列表中。
#運算符所執(zhí)行的操作可以理解為“字符串化”
當我們有一個變量 int a=10;的時候,我們想打印 :the value of a is 10
就可以寫
#define PRINT(n) printf("the value of "#n"is %d",n)
當我們按照下面的方式調(diào)用的時候:
PRINT(a);當我們把a替換到宏的體內(nèi)時,就出現(xiàn)了#a,而#a就是轉換為‘a(chǎn)’時一個字符串代碼就會預處理為:
printf("the value of 'a'is %d", a);
運行代碼就能在屏幕上打?。?/p>
the value of a is 10
##運算符
## 可以把位于它兩邊的符號合成一個符號,它允許宏定義從分離的文本片段創(chuàng)建標識符。##被稱為記號粘合
這樣的鏈接必須產(chǎn)生一個合法的標識符,否則其結果就是未定義的
這里我們想想,寫一個函數(shù)求2的數(shù)的最大值的時候,不同的數(shù)據(jù)類型就得寫不同的函數(shù)
比如:
int int_max(int x, int y)
{
return x > y ? x : y;
}
float float_max(float x, float y)
{
return x > y ? x : y;
}
但是這樣寫起來太繁瑣了,現(xiàn)在我們這樣寫代碼試試:
//宏定義
#define GENERIC_MAX(type) \
type type##_max(type x,type y)\
{\
return(x > y ? x : y);\
}
使用宏,定義不同函數(shù)
命名約定
?一般來講函數(shù)的宏的使用語法很相似,所以語言本身沒法幫我們區(qū)分二者,那我們平時的一個習慣是:
把宏名全部大寫
函數(shù)名不要全部大寫
#undef
這條指令用于移除一個宏定義
#undef NAME
//如果現(xiàn)存的一個名字需要被重新定義,那么它的舊名字需要首先被移除
?
文章來源:http://www.zghlxwxcb.cn/news/detail-828763.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-828763.html
到了這里,關于C語言系列-帶有副作用的宏參數(shù)和##&命名約定&宏替換的規(guī)則的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!