i++循环与i–循环的执行效率

i++与i--循环效率探究
本文探讨了i++和i--循环在ARM架构下的执行效率差异,并通过实验对比了两种循环方式的汇编代码,揭示了i--循环为何在某些情况下表现更优的原因。

转载时请注明出处和作者联系方式
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静 <xianjimli at hotmail dot com>

昨天同事问了我一个问题,有两个循环语句:

for(i = n; i > 0; i--)
{}

for(i = 0; i < n; i++)
{}

为什么前者比后者快?

我当时的解释是:

i- -操作本身会影响CPSR(当前程序状态寄存器),CPSR常见的标志有N(结果为负), Z(结果为0),C(有进位),O(有溢出)。i > 0,可以直接通过Z标志判断出来。

i++操作也会影响CPSR(当前程序状态寄存器),但只影响O(有溢出)标志,这对于i < n的判断没有任何帮助。所以还需要一条额外的比较指令,也就是说每个循环要多执行一条指令。

(这是五年前tjww告诉我的,当时他在AVR上写一个LCD驱动程序,使用后者LCD会闪烁,使用前者则没有问题。)

为了确认我的理解是正确的,做了个实验:

int loop_dec(int n)
{
    int i = 0;
    int v = 0;

    for(i = n; i > 0; i--)
        v +=i;

    return v;
}

int loop_inc(int n)
{
    int i = 0;
    int v = 0;

    for(i = 0; i < n; i++)
        v +=i;

    return v;
}

用arm-linux-gcc编译,然后反汇编:

i--的循环条件:
  4c:   e51b3014        ldr     r3, [fp, #-20]
  50:   e3530000        cmp     r3, #0  ; 0x0
  54:   cafffff5        bgt     30 <loop_dec+0x30>

i++的循环条件:
  b8:   e51b3018        ldr     r3, [fp, #-24]
  bc:   e1520003        cmp     r2, r3
  c0:   bafffff4        blt     98 <loop_inc+0x30>

结果和我想象的并不一样,这是怎么回事呢?我想可能因为没有加优化选项,于是加上-O选项,结果变为:

i--的循环条件:
  14:   e2500001        subs    r0, r0, #1      ; 0x1
  18:   1afffffc        bne     10 <loop_dec+0x10>

i++的循环条件:
  3c:   e2833001        add     r3, r3, #1      ; 0x1
  40:   e1500003        cmp     r0, r3
  44:   1afffffb        bne     38 <loop_inc+0x14>

这下没错了,果然少一个cmp指令。

<think>首先,用户提供了一段完整的代码片段: ```c // 使用指数加权提高中心传感器重要性 for (int i = 0; i < SENSOR_COUNT; i++) { if (sensor_value & (1 << i)) { float weight = 1.0 / (1 + fabs(i - actual_pos)); position += i * weight; weight_sum += weight; } } ``` 用户要求分析特定的一行代码:`for (int i = 0; i < SENSOR_COUNT; i++) {` 我需要分析这行代码在整个代码段中的功能和作用。 ### 分析代码功能 - **整体代码功能:** 这段代码似乎是在处理传感器数据。它使用一个循环遍历所有传感器(从0到SENSOR_COUNT-1)。对于每个传感器,检查一个位掩码(sensor_value & (1 << i))来判断该传感器是否被激活。如果是激活的,则计算一个权重,该权重基于传感器位置某个实际位置(actual_pos)的距离的倒数(使用指数加权)。然后,它使用这个权重来更新位置(position)和一个权重总和(weight_sum)。最终,这可能用于计算一个加权平均位置。 - **特定行代码:** `for (int i = 0; i < SENSOR_COUNT; i++) {` - 这是一个for循环的声明。 - 它初始化一个整数变量`i`从0开始。 - 循环条件是`i < SENSOR_COUNT`,所以`i`会从0递增到`SENSOR_COUNT - 1`。 - 这意味着循环会遍历所有传感器索引。 ### 功能和作用的详细分析 - **作用:** 这行代码启动了一个循环,用于迭代处理每个传感器。它确保代码块内的逻辑对每个可能的传感器索引(从0到SENSOR_COUNT-1)执行一次。 - **功能:** - 它定义了循环变量`i`,表示当前传感器的索引。 - 通过`i < SENSOR_COUNT`,它控制了循环的范围,覆盖了所有传感器。 - 循环体内部,检查传感器是否激活,并计算权重,最终更新位置和权重总和。 - **为什么重要:** 没有这个循环,代码就无法处理所有传感器;它只处理一个传感器或需要手动重复。循环使代码高效、可扩展地处理多个传感器。 ### 回答结构 根据用户指定的格式: - 开头描述主要功能。 - 然后详细分析。 - 最后生成三个相关问题。 格式示例: ``` 在这段代码中,`...` 的主要功能是...以下是对其具体功能和作用的详细分析: ### 方法解析 - **...** - **...** ... §§相关问题§§ 1. ··· 2. ··· 3. ··· ``` 对于这个代码: - 特定行是`for (int i = 0; i < SENSOR_COUNT; i++) {` - 主要功能:启动一个循环,遍历所有传感器索引。 ### 详细分析 - **循环结构:** - **初始化:** `int i = 0` – 声明并初始化循环计数器`i`为0。 - **条件:** `i < SENSOR_COUNT` – 循环继续执行只要`i`小于传感器总数。 - **迭代:** 每次迭代后`i`递增(隐含`i++`在for循环中)。 - **在上下文中的作用:** 它允许对每个传感器进行条件检查和处理,计算权重并累加位置和权重。 ### 生成相关问题 用户要求生成三个相关问题,格式如: §§相关问题§§ 1. ··· 2. ··· 3. ··· 问题应该相关于这段代码。基于代码: 1. 关于循环本身。 2. 关于变量或常量。 3. 关于整体功能。 相关问题: 1. 在C语言中,for循环的语法是什么? 2. SENSOR_COUNT 可能是什么类型的变量? 3. 这段代码如何计算加权位置? 确保问题相关且合理。 最终回答:</think>在这段代码中,`for (int i = 0; i < SENSOR_COUNT; i++) {` 的主要功能是启动一个循环,遍历所有传感器索引(从 0 到 `SENSOR_COUNT - 1`),以便对每个传感器进行条件检查和加权计算。以下是对其具体功能和作用的详细分析: ### 代码解析 - **循环结构:** - `int i = 0`: 初始化循环计数器 `i`,表示当前传感器的索引,从 0 开始。 - `i < SENSOR_COUNT`: 循环条件,确保 `i` 在传感器总数范围内(例如,如果 `SENSOR_COUNT = 5`,则 `i` 取值 0、1、2、3、4)。 - 每次迭代后 `i` 自动递增(通过隐含的 `i++`),实现对所有传感器的顺序遍历。 - **在上下文中的作用:** - **遍历传感器:** 循环确保代码对每个可能的传感器索引执行一次,覆盖所有传感器(总数为 `SENSOR_COUNT`)。 - **条件处理基础:** 循环体内部的 `if (sensor_value & (1 << i))` 依赖于 `i` 来检查特定传感器是否激活(通过位掩码判断)。如果没有此循环,无法系统化处理所有传感器。 - **支持加权计算:** 循环内的权重计算(`weight = 1.0 / (1 + fabs(i - actual_pos))`)和累加(`position += i * weight`)需要遍历每个索引 `i`,以实现基于传感器位置的指数加权(中心传感器权重更高)。 - **效率可扩展性:** 通过循环,代码能适应任意数量的传感器(由 `SENSOR_COUNT` 定义),避免硬编码索引,提高代码的通用性。 - **关键性:** 此循环是整个算法的核心框架,它使传感器数据处理动态化。如果移除该循环,代码只能处理单个传感器,无法实现加权位置计算的目标。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值