今天c語言有一個題目,是宏實現一個數的平方,但是要正確處理a++這樣的參數。
這個我們正常使用還是不會有什麼問題,但是一旦參數改爲a++的話,這時候就不會得到跟我們理論的正確答案了。
#define SOMETHING(b) ((b)*(b))
int main(void)
{
int a=5;
int b;
b= SOMETHING (a)*8;
printf("a = %d b = %d\n",a,b);
}
這時我們需要使用一個技巧 tfpeof
#define SOMETHING(a) ({typeof(a) _b=a;(_b*=_b);})
int main(void)
{
int a=5;
int b;
b= SOMETHING (a++)*8;
printf("a = %d b = %d\n",a,b);
}
以下比較詳細的應用轉載自 https://www.cnblogs.com/emptyYPen/p/7872604.html #define mul(a, b) a*b
a = 2; b = 3 mul(a+1, b+1);
結果是6。mul(a+1, b+1)被簡單的替代成 a+1*b+1 = 2+1*3+1 = 6。這個問題可以用()解決;
#define MAX(a, b) (a) > (b)?(a) : (b) int a = 5; int b = 2; MAX( a++, b ); //運行完後a = 7了,一下子自加了兩次。
宏替代後就是 (a++) > (b)? (a++) : (b);這明顯是違反了我們之前想要的。拿什麼來拯救宏。要不然宏也太垃圾了。答案是拿變量緩衝來解決這個問題。
#define MAX( a, b ) ({ \ int _a = a; \ int _b = b; \ (_a) > (_b)? (_a) :(_b); \ }) int a = 1, b = 3; int c = MAX( a++, b);
完全解決了重複替代可能帶來的問題,我先將你的表達式賦值給一個變量,那傳入的表達式不就是一個普通的值了嗎。然後就可以進行各種操作了。
加強該宏 的能力,如果我的a,b不是int類型的呢?
使用typeof()來獲取傳入的量是什麼類型,終於找到一個獲取變量類型的操作了。
#define MAX( a, b ) ({ \ typeof (a) _a = a; \ typeof (b) _b = b; \ (_a) > (_b)? (_a) : (_b); \ )} float a = 0.5, b = 1.2; float c = MAX( a++, b);
再進行加強一下,進行數據類型檢測是否相同,相同不會出警告,不相同gcc -Wall 會報警告。我們根據警告來查看我們程序是否有欠妥的地方。
#define MAX(a, b) ({ \ typeof (a) _a = a; \ typeof (b) _b = b; \ (void)( &_a == &_b); \ (_a) > (_b)?(_a) : (_b); \ })
說明:{ ... }程序塊不能賦值,所以在外面加個(),就能實現int c = MAX(a, b)了;
&_a 和&_b做比較,如果他們的指針類型不同,編譯器會報警告的,前面加(void)是防止編譯器報表達式&_a==&_b沒有被應用的警告。到這裏就搭建了一個健壯
的宏。
typeof ()也是66666,能用到void*身上嗎?