像标题说的那样,bug很隐蔽,所以花了不少时间debug。
先上代码:1
2
3
4
5
6
float max;
for(int i = 0; i < n; i++) {
max = MAX(max, data[data_index++]);
}
代码很简单,为了体现问题本质,我做了简化。
这段代码的目的就是从data数组中的某段连续n个元素中找出最大值,索引data_index之前被设定在data数组中的某一位置。
data_index++
会把data_index加一,然后返回加一之前的值,这看起来很正确,可以一个挨一个地遍历数组中的某段连续n个元素。
其实不然,MAX宏展开后是这样的max > data[data_index++] ? max : data[data_index++]
(去掉了括号),如果max
大于data[data_index++]
并取max
则没问题,但是如果max
不大于data[data_index++]
,那么data_index++
就做了两次。问题就出在这里。
也许把他们写在一起可以很容易看出问题,但是宏定义一般写在开头,而找最大值的这段代码在程序中部,两者相差很远。我当时费了半天劲才找到这个bug,很难想到问题出是在MAX
宏上,其实还不如说问题出在data_index++
上,这种自增操作要用就最好单独拿出来,或者保证不会被用于宏拓展,或者像《Google C++编程规范》中说的那样,尽量用内联函数来替代宏。
记下这个bug,起个提醒作用。