今天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*身上吗?