#define MIN(a,b) ((a) < (b) ? (a) : (b))
宏定义会在编译的时候进行替换展开,最好将宏中的参数用括号括起来。这样就避免了当一个表达式同时含有宏定义和其他高优先级运算符时,破坏整个表达式的运算顺序 。
上边的答案解决了一些问题,但会不会存在其他漏洞呢?如果我们用这个宏进行比较:
least = MIN(i++, j++); 替换之后 least = ((i++) < (j++) ? (i++) : (j++));
#define MIN_t(x, y) ({ \
int _x = x; \
int _y = y; \
_x < _y ? _x : _y; \
})
在语句表达式中,定义了两个局部变量 _x
、_y
来存储宏参数 x 和 y 的值,然后用 _x
、_y
比较大小。这样就避免了两次自增运算引起的问题。
然而,上边的宏定义中,也存在不足,你知道是什么吗?
那就是,临时变量的数据类型为 int 型。也就是说,这个宏定义只能比较两个整型数据。
如何完善这个宏定义,使其能够支持任意类型的数据比较大小呢?
当然,我们可以这样写:
#define MIN_t(type, x, y) ({ \
type _x = x; \
type _y = y; \
_x < _y ? _x : _y; \
})
但是,这个宏就有三个参数了,每次比较数据大小,还需要将参数类型 type 传进去。
别着急,肯定有办法弥补这个不足。也就是,想办法获取比较数据的类型。
对于 GNU C 来说,没问题。因为它扩展了一个关键字 typeof,可以获取数据类型。对于其他版本的 C 语言,需要查看手册进行考证,在此不展开介绍。
最终的优化结果如下:
#define MIN(x,y) {
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void)(&_x = &_y); \
_x < _y ? _x : _y; \
})
(void)(&x==&y)
是用于检查 x 和 y 的类型是否相同。它有两个作用:一是用来给用户提示一个警告。对于不同类型的指针比较,编译器会发出一个警告,提示两种数据的类型不同。
二是两个数进行比较运算,运算的结果却没有用到,有些编译器可能会给出一个 warning,加一个(void)后,就可以消除这个警告。
END
→点关注,不迷路←
文章引用微信公众号"嵌入式微处理器",如有侵权,请联系管理员删除!