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

来源:互联网 发布:晨曦软件 编辑:程序博客网 时间:2024/04/30 11:38

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

下面以+=为例

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),那么我们应尽量使用复合赋值操作符,不失效率同时书写方便。

原创粉丝点击