C语言自增自減问题总结

在程序设计中,经常遇到“i=i+1”和“i=i-1”这两种极为常用的操作。C语言为这种操作提供了两个更为简洁的运算符,即++和--,分别叫做自增运算符和自减运算符。它们是单目运算符,是从右向左结合的算术运算符。学习和应用这两个运算符时应注意以下几点:

我将自增自减运算符和变量结合在一下的表达式称为自增自减表达式,如x++,--I等。通常情况下就有以下的结论:

1‘’前缀表达式:++x, --x; 其中x表示变量名,先完成变量的自增自减1运算,再用x的值作为表达式的值;即“先变后用”,也就是变量的值先变,再用变量的值参与运算。

2、后缀表达式:x++, x--;  先用x的当前值作为表达式的值,再进行自增自减1运算。即“先用后变”,也就是先用变量的值参与运算,变量的值再进行自增自减变化,。

如a=8; b=a++; c=++a; 其中赋给变量b的值为表达式(a++)的值,不应该理解为a的值,则b=8, c=10;

3、自增、自减运算只能用于单个变量,只要是标准类型的变量,不管是整型、实型,还是字符型变量等,但不能用于表达式或常量。如:++(a+b), 与5++,  const int N=0; N++; 等都是错误的。 而i+++j++、++i+(++j)、++a+b++、++array[--j];等,这些都是合法的。

4、再说结合性与结合方向

编译器对程序编译时,从左到右尽可能多地将字符组合成一个运算符或标识符,因此i+++j++等效于(i++)+(j++),两个“++”作用的对象都是变量,这是合法的;而++i+++j等效于++(i++)+j,第1个“++”作用的对象是表达式“i++”,这是不允许的。

自增自减运算符是单目运算符,其结合性是从右到左。表达式k=-i++等效于k=(-i)++还是k=-(i++)?。因为负号也是单目运算符,因此,上式从右到左结合,等效于k=-(i++);若i=5,则表达式k=-i++运算之后k的值为-5,i的值为6。此赋值表达式的值即为所赋的值-5。不要因为k=-i++等效于k=-(i++)就先做“++”运算!这里采用的是“先用后变”,即先拿出i的值做负号“-”运算,把这个值赋给变量k之后变量i才自增。

5、注意运算符的副作用

C语言允许在一个表达式中使用一个以上的赋值类运算,包括赋值运算符、自增运算符、自减运算符等。这种灵活性使程序简洁,但同时也会引起副作用。这种副作用主要表现在:使程序费解,并易于发生误解或错误。例如,当i=3时,表达式(i++)+(i++)+(i++)的值为多少,各种教材说法不统一。对于这种情况,为了增强程序的可读性与可移植性,在一个表达式中,就应该用简单的自增与自减运算,不用对同一变量进行多次自增自减运算的表达式,否则,其他人可能看不懂,换个运行环境也可能是不同的结果。我相信,在考试试题中也是不会出现象这种有不同结果的试题的,请读者放心。当然,为了丰富知识,了解一下这些内容也是必要的。

以下内容是经查阅资料所得:用各种表达式上机测试,给出VC++环境下连续自增(自减)运算规则:

1、 在一般表达式中和在函数参数中计算的结果相同(这一点与Turbo C环境不同);

2、 后缀:同表达式中Turbo C的情况相同:先统一取值后依次自增,如:

int a,i=5; a=i+++i+++i++; a=15, i=8.

3、 前缀:前两个自增同Turbo C,即依次自增后统一取值,后面的每个自增后即取值,如:

int a, i=5; a= ++i +(++i)+(++i); a=22, i=8.

4、 前后缀混合的情况:

(1) 一般情况:表达式中自左向右计算,参数自右向左运算。前缀自增后取值;后缀(或变量)取值依其所处位置而定,有连续多个将统一取值,其自增在语句结束前进行。

(2) 前后缀各有一个的情况:设int i=5; 由于i++*++i应满足交换率与++i*i++相同,规定按后者计算故为36。实验2内容4:int i=5; printf("%d,%d\n", --i, i++*++i ); 打印5,36。

(3) 若i++或++i或两者有多于一个的情况:++i有两个以上在一起时最左边的连续自增同3、,其余每个自增后取值,如:int i=5;

printf("%d\n%d\n",--i,(++i)+(i++)+(i++)+(++i)); 打印6和25

printf("%d\n%d\n",--i,(++i)+(++i)+(++i)+(++i)+(i++)); 打印8和40

printf("%d\n%d\n",--i,(++i)+(++i)+(++i)+i+(++i)+(++ i)); 打印9和49

(4) 函数参数中有括号时,括号参数优先计算,其余参数仍自右向左计算,如:

int i=9,j=8; printf("%d %d\n", (++i, j--), ++i); 打印8 11

printf("%d %d %d\n", (++i, j--), ++i, i); 打印8 11 10

(5) 最后i的值等于原值加总自增次数减自减的次数.

克服这类副作用的方法是,尽量把程序写得易懂一些,即将费解处分解成若干个语句。如:k=i+++j:可写成k=i+j:i++:而类似(i++)+(i++)+(i++)这类连续自增、自减的运算最好不要使用,以避免疑团的出现,同时也可减少程序出错的可性能。

最后感谢为了得到正确结果而花较多时间去上机实践的人们,祝你幸福快乐!

最新文章

  1. Third Day(上班第四天):Android开发环境配置问题相关
  2. iOS-保存照片或者视频到自定义相薄中以及读取数据
  3. LaTex 使用 - 配置
  4. jQuery 控制表单和表格
  5. setImageBitmap和setImageResource
  6. yii框架各种防止sql注入,xss攻击,csrf攻击
  7. centos下查看rpm包安装位置
  8. Android Service with Delphi 10 Seattle
  9. ueditor的过滤、转义、格式丢失问题
  10. Python模块发布
  11. POJ 1018 Communication System(贪心)
  12. 练习:javascript轮播图效果
  13. Kylin引入Spark引擎
  14. pfSense用户界面汉化翻译教程
  15. SSH下authorized_keys, id_rsa, id_rsa.pub, known_hosts作用
  16. 雷林鹏分享:C# 事件(Event)
  17. eclipse项目转移至IDEA与IDEA tomcat报错(idea自带tomcat版本太高)与war包部署到win服务器与idea提交git的总结
  18. java中Scanner的nextLine()和next()的区别
  19. c#开源项目[转]
  20. 【BZOJ】2555: SubString(后缀自动机)

热门文章

  1. java并发编程基础—生命周期与线程控制
  2. VM虚拟机桥接模式无法联网、NAT模式能正常联网
  3. FormData提交文件(十四)
  4. Windows Server创建域控制器
  5. 一文说清OpenCL框架
  6. 构建前端第10篇之---Function.prototype.call()
  7. Tom_No_02 Servlet向流中打印内容,之后在调用finsihResponse,调用上是先发送了body,后发送Header的解释
  8. 微信小程序对接显示阿里云数据库数据
  9. C#曲线分析平台的制作(五,Sqldependency+Signalr+windows 服务 学习资料总结)
  10. 利用postman进行api接口开发