转载至:https://mp.weixin.qq.com/s/0ZVNbTj7fGs8Gi03vj541A
公众号:LINUX内核之旅

图片说明
上述这种写法没能解决宏参数++问题

图片说明
这种写法解决了
首先,它的结构是这样({语句1;语句2;语句3;语句4;}),根据GCC的扩展特性,这个表达式最终的值应该是语句4的值。

语句1typeof(x) _max1 = (x);是定义了一个同x的类型的局部变量_max1,并把x的数值赋值给了_max1。

语句2typeof(y) _max2 = (y);是定义了一个同y的类型的局部变量_max2,并把x的数值赋值给了_max2。

语句3(void) (&_max1 == &_max2);对于程序的执行是没有任何作用的,它的作用在于判断两个数的类型是否相同,如果类型不同,就会在编译过程中抛出一个警告。因为x和y的类型不一样,其指针类型也会不一样,两个不一样的指针类型进行比较操作,会抛出一个编译警告。如char * x; int * y, 然后x==y, 这个判断因为一个是char * 一个是int *,所以gcc在编译时会产生一个warning,这样可以避免一些潜在的错误发生。
在这个宏定义中,先根据x和y的类型生成了两个局部变量_max1和_max2,之后判断其类型,比较其大小,返回较大的一个,这样就保证了宏参数只会被执行一次,避免了之前实验中出现的错误结果。要将x和y重新定义为_max1和_max2是为了避免输入参数和宏定义内部使用的局部变量重名,重名会导致在宏定义的语句块外层同名变量被内层变量作用而出现错误,这也就是前面提到的为什么会执行两次y++而出现错误的原因了。