C语言获取循环数

在很多时候,我们需要循环序列,比如循环读取数组的8个元素,便需要索引指针(index)从0-7-0变化,
常规而言,会写出下面的代码

if 语句
1
2
3
4
if (++index >= 8)
{
index = 0;
}

或者

?表达式
1
index = (++index >= 8)? 0:index;

观察到这是连续循环操作,所以我们可以用%的方式,来省掉一个判断语句,如下所示

取余语句
1
index = (++index)%8;

因为++优先级高于%,所以进而简化为

正确写法
1
index = ++index%8;

特别注意: 这里是前置递加操作,不要写成后置,如下所示

错误写法
1
index = index++%8;

如果写成后置的,会出现什么情况呢?

分别将二者反汇编(ARM反汇编),如下所示

错误写法 index = index++%8
1
2
3
4
5
MOVS      R1, #8
MOVS R0, R4
UDIV R4, R0, R1
MLS R4, R4, R1, R0
ADDS R4, R4, #1
正确写法 index = ++index%8
1
2
3
4
5
ADDS      R4, R4, #1
MOVS R0, #8
UDIV R1, R4, R0
MLS R1, R1, R0, R4
MOVS R4, R1

翻译成C语言如下

错误
1
2
index = index%8;
index = index + 1;
正确
1
2
index = index + 1;
index = index%8;

编译器不支持取余运算,所以需要数学计算,取余等于

A%B = A - (A/B)*B

对此,不做过多解释,重点关注ADD那句的位置,正确的表达式会先计算index的值,然后再取余;
而错误的,则先取余,再递增;

所以,正确的语句index = ++index%8会输出0 - 1 - 2 ... 7 - 0序列,错误的会输出1 - 2 ... 7 - 8 - 1序列