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