关于C语言中的复合赋值操作符

复合赋值操作符有 +=, -=, *=, /=,%=, <<=, >>=, &=, ^=, |=。

下面以+=为例

a += expression        (1)

等价于:

a = a + expression   (2)

但是,这里是有区别的,(1)式中的a(如数组下标访问的元素)只求值一次,(2)式中的a求值两次,当然编译器也许会优化,可能会使得(2)式效果和(1)式一样,但是有例外的情况,编译器是无法优化的。如:

int f(int x){return x;}
 
int a[10] = {0};
int x = 2;
 
a[f(x) + 1] += 1;              // (1)
a[f(x) + 1] = a[f(x) +1] +1;      // (2)

以上两个表达式机器代码是完全不同的,对于(2)式,由于是调用函数,编译器并不能确定每次函数都返回相同的值(即是否有副作用),所以编译器对此无能为力,不能对此优化,因此也就会去乖乖地调用两次函数,而(1)式只调用一次函数,参见VS2010下的汇编代码:

    a[f(x) + 1] = a[f(x) +1] +2;
013B1413  mov        eax,dword ptr [ebp-3Ch] 
013B1416  push       eax 
013B1417  call       @ILT+110(_f) (13B1073h) 
013B141C  add        esp,4 
013B141F  mov        esi,dword ptr [ebp+eax*4-2Ch] 
013B1423  add        esi,2 
013B1426  mov        ecx,dword ptr [ebp-3Ch] 
013B1429  push       ecx 
013B142A  call       @ILT+110(_f) (13B1073h) 
013B142F  add        esp,4 
013B1432  mov        dword ptr [ebp+eax*4-2Ch],esi 
    a[f(x) + 1] += 2;
013B1436  mov        eax,dword ptr [ebp-3Ch] 
013B1439  push       eax 
013B143A  call       @ILT+110(_f) (13B1073h) 
013B143F  add        esp,4 
013B1442  lea         ecx,[ebp+eax*4-2Ch] 
013B1446  mov        dword ptr [ebp-104h],ecx 
013B144C  mov        edx,dword ptr [ebp-104h] 
013B1452  mov        eax,dword ptr [edx] 
013B1454  add        eax,2 
013B1457  mov        ecx,dword ptr [ebp-104h] 
013B145D  mov        dword ptr [ecx],eax

因此,如果我们能确定表达式中不含有副作用的元素(如上面的函数f),那么我们应尽量使用复合赋值操作符,不失效率同时书写方便。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值