c语中的自增自减

上传人:小** 文档编号:62370353 上传时间:2018-12-20 格式:DOC 页数:15 大小:420KB
返回 下载 相关 举报
c语中的自增自减_第1页
第1页 / 共15页
c语中的自增自减_第2页
第2页 / 共15页
c语中的自增自减_第3页
第3页 / 共15页
c语中的自增自减_第4页
第4页 / 共15页
c语中的自增自减_第5页
第5页 / 共15页
点击查看更多>>
资源描述

《c语中的自增自减》由会员分享,可在线阅读,更多相关《c语中的自增自减(15页珍藏版)》请在金锄头文库上搜索。

1、C语中的自增自减摘要运算符多、操作灵活是C语言的一大特色。在诸多运算符中,最难理解、最容易出错的便是自增、自减运算符。本文就这两个运算符使用中应注意的问题进行了分析介绍。关键词C语言自增运算符自减运算符Points for Attention of Using Auto-increasing and Auto-decreasing Operators in Language CWang HongAbstract:Many operators and convenient operation characterize language C. Among those operators, the

2、most difficult to understand and the easiest to mistake are auto-increasing and auto-decreasing operators. This paper analyses the notices in using these two operators.Key words:Language Cauto-increasing operatorsauto-decreasing operators在程序设计中,经常遇到“i=i+1”和“i=i-1”这两种极为常用的操作。变量i被称为“计数器”,用来记录完成某一操作的次数

3、。C语言为这种计数器操作提供了两个更为简洁的运算符,即+和-,分别叫做自增运算符和自减运算符。它们是从右向左结合的一元算术运算符,优先级为2。学习和应用这两个运算符时应注意以下几点:1注意表达式的值和变量值的区别以自增运算符为例,当自增运算符+作用于一个变量时,例如:当i=3时+i这个算术表达式的值为4,同时变量i的值也由原来的3改变为4。一般情况下,计算表达式后不改变变量本身的值,而+运算符和-运算符组成的表达式计算后,则改变变量的值,这称为运算符的副作用。这类运算符在计算表达式时,一定要注意区分表达式的值和变量的值。2注意前缀运算和后缀运算的区别仍以自增运算符为例,该运算符可作用在变量之前

4、,例如前面所讲的+i,称为前缀运算;也可作用在变量之后,例如i+,称为后缀运算。在这两种运算中,表达式的值不同:前缀运算后,表达式的值为原变量值加1;后缀运算后,表达式的值仍为原变量值;而变量值不论前缀运算还是后缀运算都加1。自减运算符与自增运算符类似,只要将加1改为减1即可。即前缀运算是“先变后用”,而后缀运算是“先用后变”。3注意运算符的运算对象自增、自减运算符只能作用于变量,而不能作用于常量或表达式。因为自增、自减运算符具有对运算量重新赋值的功能,而常量、表达式无存储单元可言,当然不能做自增、自减运算。只要是标准类型的变量,不管是整型、实型,还是字符型、枚举型都可以作为这两个运算符的运算

5、对象。如以下四个表达式都是合法的:i+j+、+i+(+j)、+a+b+、+array-j;而+6、(i+j)+、A+、+i+j、(&p)+这五个表达式却是不合法的。为什么i+j+合法,而+i+j却不合法?C的编译器对程序编译时,从左到右尽可能多地将字符组合成一个运算符或标识符,因此i+j+等效于(i+)+(j+),两个“+”作用的对象都是变量,这是合法的;而+i+j等效于+(i+)+j,第1个“+”作用的对象是表达式“i+”,这是不允许的。4注意运算符的结合方向表达式k=-i+等效于k=(-i)+还是k=-(i+)?因为负号运算符和自增运算符优先级相同,哪一个正确就得看结合方向。自增、自减运算

6、符及负号运算符的结合方向是从右向左。因此,上式等效于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+)的值为多少,各种教材说

7、法不统一:有的认为是9(3+3+3,如谭浩强的C程序设计,清华大学出版社,1991);也有的认为是12(3+4+5,如王森的C语言程序设计,电子工业出版社,1995)。到底哪一个说法正确呢?不妨看看下面这个程序的运行情况:main( )int i,j;i=3; j=(i+)+(i+)+(i+); printf(“nj=%d,”j);i=3; printf(“j=%d”,(i+)+(i+)+(i+);在TC3.0上运行,其结果则是:j=9,j=12,究其原因,“先用后变,先变后用“中的“先”和“后”是一个模糊的概念,很难给出顺序或时间上的准确定论。“先”到什么时候,“后”到什么程度?没有此方面的

8、详细资料可供查询。为此,笔者用各种表达式上机测试,结果发现当表达式的值作为printf函数的直接输出对象时,“先变后用”和“先用后变”中的“后”就是指+i和i+这一小项运算完之后,如上面程序中最后一个语句中的输出对象:第一个(i+)取出i的值3以后i立即变为4,第二个(i+)取出i的值4以后i立即变为5,第三个(i+)取出i的值5以后i立即变为6,这样输出的结果便是3+4+5这个表达式的值,即12。而在其它一些表达式或语句中,“变”或“用”的时机却很难掌握。下列各式中变量j的值都是在i=3,k=1的前提下求出的:后缀运算:(1)j=(5,6,(i+)+(i+)+(i+): j=9(3+3+3)

9、(2)j=(k+,6,(i+)+(i+)+(i+): j=9(3+3+3)(3)j=1?(i+)+(i+)+(i+): 0: j=9(3+3+3)(4)j=i?(i+)+(i+)+(i+): 0: j=12(3+4+5)(5)j=k+?(i+)+(i+)+(i+): 0: j=12(3+4+5)前缀运算:(6)j=(5,i,(+i)+(+i)+(+i): j=18(6+6+6)(7)j=(5,k+,(+i)+(+i)+(+i): j=15(4+5+6)(8)j=1?(+i)+(+i)+(+i): 0: j=18(6+6+6)(9)j=1?(k+,(+i)+(+i)+i): 0: j=15(4+

10、5+6)(10)j=k+?(+i)+(+i)+(+i): 0: j=15(4+5+6)其中(3)和(4)、(6)和(7)、(8)和(10)等这几对类型相同的表达式却得到完全不同的运算结果,令人费解!由此可见,在一般表达式中,就i+来说,“先用后变”中何时“变”很难说得清楚;对+i来说,“先变后用”中何时“用”也不易道白(自减运算符与此类似)。因此,读者在使用这类运算符时一定要特别注意。克服这类副作用的方法是,尽量把程序写得易懂一些,即将费解处分解成若干个语句。如:k=i+j:可写成k=i+j:i+:而类似(i+)+(i+)+(i+)这类连续自增、自减的运算最好不要使用,以避免疑团的出现,同时也

11、可减少程序出错的可性能。在程序设计中,效率和易读性是一对主要矛盾。为了提高程序的效率,需要用技巧把程序写得尽可能简洁一些,但这样有可能降低程序的可读性和可理解性。可读性差的程序容易隐藏错误且难于纠正,不易维护,降低了程序的可靠性。鉴于“软件危机”的教训,人们在程序设计时遵守的基本规范是:可靠性第一,效率第二。为了保证可靠性,程序必须清晰易读,而表达式的清晰易读是十分重要的方面。因此,在C程序设计中,要慎重使用自增、自减运算符,特别是在一个表达式中不要多处出现变量的自增、自减等运算。安装教科书上说明:“函数参数的求值顺序是自右向左”更是大错特错。楼主,C语言跟大多数语言一样,没有规定表达式的求值

12、顺序,除了以下几个顺序点:;(分号,标志一条语句结束),(逗号操作符,函数参数列表里面的逗号只起分隔作用,不是逗号操作符)&和|(逻辑与,逻辑或)? : (条件运算符)()(if,while,for, do.while,以及函数调用)这些统称为顺序点,它们的求值顺序有规定。我这里只给你说明逗号操作符,其他的不一一作介绍(不然能写一大篇呢),你自己参考相关资料。逗号表达式最简单的情形如下:exp1, exp2;C语言保证exp1在exp2之前求值,并且exp1求值的副作用保证在逗号之前生成。所以象下面这个逗号表达式:int i = 1;i+, (i = 2);最后的值就是1,因为逗号表达式的前半

13、部分i+的副作用(i自增1)在逗号之前已经生成,所以当执行到(i = 2)的时候,i的值已经是2了,所以i = 2成立,(i = 2)的值便作为整个逗号表达式的值。但是,对函数原型,函数定义,函数调用,C语言里面明确说明,参数列表里面的逗号不是逗号操作符,只起到分隔作用,所以这里的逗号不再是一个顺序点,那它前后的表达式的求值顺序就是任意的,并且所有带副作用的表达式的副作用都要等到下一个顺序点之后才是确定的,也就是说你只有等到下一个顺序点之后,你才能准确得依赖这些表达式产生的副作用。所以,像这样的函数调用foo(i+, +i);是得不到准确的结果的。因为这里逗号不是逗号操作符,所以就算编译器选择

14、的是从左到右的求值顺序,由于C语言不再保证i+的副作用在逗号之前生成,算到+i的时候,都不确定i到底有没有自增1,不确定性就在这里产生了。再者,如果编译器选择的是从右到左求值,同样产生不确定性,这样一来,传进函数foo的两个参数的值就可能不同,那么最后的结果当然也就不同了。你这里一样,printf是一个函数,printf(%d,%d,%dn,+i,-i,-i+); 是函数调用,括号内的所有逗号都不是逗号操作符,而只起到分隔参数的作用。所以+i,-i,-i+这三个表达式的求值顺序是任意的,编译器想怎么算就怎么算,不同的编译器的“想法”可能相同可能不同,结果就可能一样可能不一样。这才是楼上的各位得

15、到不同结果的真正原因!楼主要好好参考顺序点的定义和作用,并且牢记下面这条规则:C语言里面明确指出:在两个顺序点之间两次改变同一个变量的任何尝试得到的结果都是不确定的!你这里int i=10; printf(%d,%d,%dn,+i,-i,-i+); 的两个顺序点分别是int i=10;的分号,和包围printf的参数的括号,C语言只保证位于两个顺序点之间的表达式求值产生副作用在第二个顺序点之前生成,但不保证两个顺序点之间所有表达式的求值顺序。你这里+i,-i,-i+三个表达式企图在两个顺序点前一个分号和()之间三次改变同一个变量i的值,所以结果注定是不确定的。至于为什么C语言要规定相邻顺序点之间的表达式以任意顺序求值,是为了给编译器更多的自由空间,让底层运算操作能由编译器调度安排从而使运算更有效地执行。 1自加运算符(+)使用自加运算符时应注意以下5个事项: 自加运算符“+”的运算结果是使运算对象增1。例如,i+相当于

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 商业/管理/HR > 管理学资料

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号