开发者社区> 华章计算机> 正文

《编写高质量代码:改善c程序代码的125个建议》——建议16-1:尽量使用复合赋值运算符

简介:
+关注继续查看

本节书摘来自华章计算机《编写高质量代码:改善c程序代码的125个建议》一书中的第2章,建议16-1,作者:马 伟 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

建议16-1:尽量使用复合赋值运算符

C语言不但提供了最基本的赋值运算符“=”,而且为了简化程序并提高编译效率,还允许在赋值运算符“=”之前加上其他运算符,这样就构成了复合赋值运算符(即 /=、*=、%=、+=、-=、<<=、>>=、&=、^= 与 |= )。示例代码如下:

a/=b;        /* 等价于 a=a/b; */
a*=b;        /* 等价于 a=a*b; */
a%=b;        /* 等价于 a=a%b; */
a+=b;        /* 等价于 a=a+b; */
a-=b;        /* 等价于 a=a-b; */
a<<=b;       /* 等价于 a=a<<b; */
a>>=b;       /* 等价于 a=a>>b; */
a&=b;        /* 等价于 a=a&b; */
a^=b;        /* 等价于 a=a^b; */
a|=b;        /* 等价于 a=a|b; */
a+=2+1;      /* 等价于 a=a+(2+1); */
a/=2*10-5;   /* 等价于 a=a/(2*10-5); */

对于表达式a/=b与a=a/b,有读者会问,它们两者之间究竟有什么区别呢?
答案很简单,对于a=a/b,a需要求值两次;而对于a/=b,a仅需要求值一次。一般来说,这种区别对程序的运行没有多大影响。编译器一般会进行优化,使两种表达式的运行效果
一样。
当然,也有例外的情况,这时编译器无法进行优化。当表达式作为函数的返回值时,函数就会被调用两次,例如:

int f(int x)
{
    return x;
}  
int main (void)
{
    int a[10] = {0};  
    int x = 2;    
    a[f(x) + 1] += 1;           
    a[f(x) + 1] = a[f(x) +1] +1;     
    return 0;
}
在上
面```  
的代码中,由于语句“a[f(x) + 1] = a[f(x) +1] +1”是调用函数,编译器并不能确定每次函数调用都返回相同的值,所以编译器对此也无能为力,无法进行优化,因此只好乖乖地调用两次函数;而语句“a[f(x) + 1] += 1”则只调用一次函数。
上面的代码在Microsoft Visual Studio 2010集成开发环境VC++的Debug模式下将生成如下汇编代码:

a[f(x) + 1] += 1;
013F3763 mov eax,dword ptr [ebp-3Ch]
013F3766 push eax
013F3767 call f (13F11DBh)
013F376C add esp,4
013F376F lea ecx,[ebp+eax*4-2Ch]
013F3773 mov dword ptr [ebp-104h],ecx
013F3779 mov edx,dword ptr [ebp-104h]
013F377F mov eax,dword ptr [edx]
013F3781 add eax,1
013F3784 mov ecx,dword ptr [ebp-104h]
013F378A mov dword ptr [ecx],eax

a[f(x) + 1] = a[f(x) +1] +1;     

013F378C mov eax,dword ptr [ebp-3Ch]
013F378F push eax
013F3790 call f (13F11DBh)
013F3795 add esp,4
013F3798 mov esi,dword ptr [ebp+eax*4-2Ch]
013F379C add esi,1
013F379F mov ecx,dword ptr [ebp-3Ch]
013F37A2 push ecx
013F37A3 call f (13F11DBh)
013F37A8 add esp,4
013F37AB mov dword ptr [ebp+eax*4-2Ch],esi

从上面的汇编代码中可以很清楚地看到两者之间的区别,使用普通的赋值运算符会加大程序的开销,从而使程序的效率降低。因此,如果能确定表达式中不含具有副作用的元素(如上面的函数f),那么应该尽量使用复合赋值运算符来代替普通的赋值运算符,不过一定要注意程序的可读性。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
《Java 7程序设计入门经典》一2.11 速记赋值运算符
本节书摘来自华章出版社《Java 7程序设计入门经典》一书中的第2章,第2.11节,作者(美)Herbert Schildt Dale Skrien,更多章节内容可以访问云栖社区“华章计算机”公众号查看
1187 0
【高质量代码】如何写出更高质量的C/C++代码(1):内存管理
内存的管理是C/C++开发程序过程中的一个比较麻烦的问题。对于经验不是足够丰富的程序员来说,开发比较复杂的程序的时候几乎肯定会遇到内存管理方面的bug。
979 0
visual studio编写C#代码时“未能从程序集.....中加载类型”和“找不到方法”的一种可能的解决办法
编译前报错:$exception    {"未能从程序集“XSW.MySQLDAL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”中加载类型“XSW.MySQLDAL.EnterpriseLibraryProductDAL”。
1395 0
10057
文章
0
问答
来源圈子
更多
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载