c语中的自增自减(1)

上传人:m**** 文档编号:119449760 上传时间:2022-07-15 格式:DOC 页数:16 大小:87KB
返回 下载 相关 举报
c语中的自增自减(1)_第1页
第1页 / 共16页
c语中的自增自减(1)_第2页
第2页 / 共16页
c语中的自增自减(1)_第3页
第3页 / 共16页
亲,该文档总共16页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
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 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 C auto-increasing operators auto-decreasing operators在程序设计中,经常遇到“i二i+1”和“i二i-1”这两种极为常用的操作。变量i被 称为“计数器”,用来记录完成某一操作的次数。C语言为这种计数器操作提供了两个更为 简洁的运算符,即+和-,分别叫做自增运算符和自减运算符。它们是从右向左结合的一元 算术运算符,优先级为2。学习和应用这两个运算符时应注意以下几点:1 注意表达式的值和变量值的区别以自增运算符为例,当自增运算符+作用于一个变量时,例如:当i二3时+i这个 算术表达式的值为4,同时变量i的值也由原来的3改变为4。一般情况下,计算表达式后 不改变变量本身的值,而+运算符和-运算符组成的表达式计算后,则改变变量的值,这称 为运算符的副作用。这类运算符在计算表达式时,一定要注意区分表达式的值和变量的值。2 注意前缀运算和后缀运算的区别仍以自增运算符为例,该运算符可作用在变量之前,例如前面所讲的+i,称为前 缀运算;也可作用在变量之后,例如i+,称为后缀运算。在这两种运算中,表达式的值不 同:前缀运算后,表达式的值为原变量值加1;后缀运算后,表达式的值仍为原变量值;而 变量值不论前缀运算还是后缀运算都加1。自减运算符与自增运算符类似,只要将加1改为 减1即可。即前缀运算是“先变后用” ,而后缀运算是“先用后变” 。3 注意运算符的运算对象自增、自减运算符只能作用于变量,而不能作用于常量或表达式。因为自增、自减 运算符具有对运算量重新赋值的功能,而常量、表达式无存储单元可言,当然不能做自增、 自减运算。只要是标准类型的变量,不管是整型、实型,还是字符型、枚举型都可以作为这 两个运算符的运算对象。如以下四个表达式都是合法的: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+)因为负号运算符和自增运算符优先级 相同,哪一个正确就得看结合方向。自增、自减运算符及负号运算符的结合方向是从右向左。 因此,上式等效于k=-(i+);若匚二5,则表达式k=-i+运算之后k的值为-5, i的值为6。 此赋值表达式的值即为所赋的值-5。不要因为k=-i+等效于k=-(i+)就先做“+运算! 这里采用的是“先用后变”,即先拿出i的值做负号“-”运算,把这个值赋给变量k之后 变量i才自增。5 注意运算符的副作用C语言允许在一个表达式中使用一个以上的赋值类运算,包括赋值运算符、自增运 算符、自减运算符等。这种灵活性使程序简洁,但同时也会引起副作用。这种副作用主要表 现在:使程序费解,并易于发生误解或错误。例如,当i二3时,表达式(i+) + (i+) + (i+) 的值为多少,各种教材说法不统一:有的认为是9(3+3+3,如谭浩强的C程序设计,清华 大学出版社,1991);也有的认为是12(3+4+5,如王森的语言程序设计,电子工业出版 社,1995)。到底哪一个说法正确呢不妨看看下面这个程序的运行情况:main()in t i,j;i=3; j=(i+) + (i+) + (i+); printf(“nj=%d,”j);i=3; printf(“j=%d”,(i+)+(i+)+(i+);在上运行,其结果则是:j=9,j=12,究其原因,“先用后变,先变后用“中的“先” 和“后”是一个模糊的概念,很难给出顺序或时间上的准确定论。“先”到什么时候,“后” 到什么程度没有此方面的详细资料可供查询。为此,笔者用各种表达式上机测试,结果发现当表达式的值作为prin tf函数的直 接输出对象时,“先变后用”和“先用后变”中的“后”就是指+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)(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+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+)这类连续自增、自减的 运算最好不要使用,以避免疑团的出现,同时也可减少程序出错的可性能。在程序设计中,效率和易读性是一对主要矛盾。为了提高程序的效率,需要用技巧 把程序写得尽可能简洁一些,但这样有可能降低程序的可读性和可理解性。可读性差的程序 容易隐藏错误且难于纠正,不易维护,降低了程序的可靠性。鉴于“软件危机”的教训,人 们在程序设计时遵守的基本规范是:可靠性第一,效率第二。为了保证可靠性,程序必须清 晰易读,而表达式的清晰易读是十分重要的方面。因此,在c程序设计中,要慎重使用自增、 自减运算符,特别是在一个表达式中不要多处出现变量的自增、自减等运算。安装教科书上说明:“函数参数的求值顺序是自右向左”更是大错特错。楼主,C语言 跟大多数语言一样,没有规定表达式的求值顺序,除了以下几个顺序点:;(分号,标志一条语句结束),(逗号操作符,函数参数列表里面的逗号只起分隔作用,不是逗号操作符)&和| (逻辑与,逻辑或):(条件运算符)()(if, while, for, do.while,以及函数调用)这些统称为顺序点,它们的求值顺序有规定。我这里只给你说明逗号操作符,其他的不 一一作介绍(不然能写一大篇呢),你自己参考相关资料。逗号表达式最简单的情形如下:exp1, exp2;C语言保证exp1在exp2之前求值,并且exp1求值的副作用保证在逗号之前生成。所 以象下面这个逗号表达式:int i 二 1;i+, (i 二二 2);最后的值就是1,因为逗号表达式的前半部分i+的副作用(i自增1)在逗号之前已经生 成,所以当执行到(i二二2)的时候,i的值已经是2 了,所以i二二2成立,(i二二2)的值 便作为整个逗号表达式的值。但是,对函数原型,函数定义,函数调用,C语言里面明确说明,参数列表里面的逗号 不是逗号操作符,只起到分隔作用,所以这里的逗号不再是一个顺序点,那它前后的表达式 的求值顺序就是任意的,并且所有带副作用的表达式的副作用都要等到下一个顺序点之后才 是确定的,也就是说你只有等到下一个顺序点之后,你才能准确得依赖这些表达式产生的副 作用。所以,像这样的函数调用foo(i+, +i);是得不到准确的结果的。因为这里逗号不是逗号操作符,所以就算编译 器选择的是从左到右的求值顺序,由于C语言不再保证i+的副作用在逗号之前生成,算到 +i的时候,都不确定i到底有没有自增1,不确定性就在这里产生了。再者,如果编译器 选择的是从右到左求值,同样产生不确定性,这样一来,传进函数f。的两个参数的值就可 能不同,那么最后的结果当然也就不同了。你这里一样,printf是一个函数,prin tf(%d,%d,%dn,+i, i,-i+);是函数调用,括号内的所有逗号都不是逗号操作符,而只起到分隔参数的作用。所以 +i,-i,-i+这三个表达式的求值顺序是任意的,编译器想怎么算就怎么算,不同的编译器 的“想法”可能相同可能不同,结果就可能一样可能不一样。这才是楼上的各位得到不同结 果的真正原因!楼主要好好参考顺序点的定义和作用,并且牢记下面这条规则:C语言里面明确指出:在两个顺序点之间两次改变同一个变量的任何尝试得到的结果都 是不确定的!你这里int i=10;prin tf(%d,%d,%dn,+i, i,-i+);的两个顺序点分别是int i=10;的分号,和包围prin tf的参数的括号,C语言只保证位 于两个顺序点之间的表达式求值产生副作用在第二个顺序点之前生成,但不保证两个顺序点 之间所有表达式的求值顺序。你这里+i,-i,-i+三个表达式企图在两个顺序点前一个分号 和()之间三次改变同一个变量i的值,所以结果注定是不确定的。至于为什么C语言要规定 相邻顺序点之间的表达式以任意顺序求值,是为了给编译器更多的自由空间,让底层运算操 作能由编译器调度安排从而使运算更有效地执行。1自加运算符(+)使用自加运算符时应注意以下5个事项: 自加运算符“+ ”的运算结果是使运算对象增1。例如,i+相当于匸i+1。 运算符“+”是单目运算符,运算对象可以是整型变量也可以是实整型变量, 不能是常量或表达式。所以像+3、(i+j) +是不合法的。 用自加运算符构成表达式时,既可以是前缀形式,也可以是后缀形式。这两 种形式对于变量来说,其结果都是加1,但对表达式来说其值是不同的。 运算符“+”的结合方向是“自右向左”。 不要在一个表达式中对同一个变量进行多次诸如i+或+i等运算。2自减运算符(-)使用自减运算符时应注意以下5个事项: 自减运算符“一”的运算结果是使运算对象减1。例如,i相当于i二iT。 运算符“-”是单目运算符,运算对象可以是整型变量也可以是实整型变量, 不能是常量或表达式。 用自减运算符构成表达式时,既可以是前缀形式,也可以是后缀形式。这两 种形式对于变量来说,其结果都是减1,但对表达式来说其值是不同的。 运算符“-”的结合方向是“自右向左”。 不要在一个表达式中对同一个变量进行多次诸如i一或一i等运算。对于代码int i = 3; i = i+;不同编译器给出不同的结果,有的为3,有的为4,哪个是正确的?没有正确答案;这个表达式无定义。参见问题,和 。同时注意, i+和+i都不同于i+1。如果你要使i自增1,使用i二i+1, i+=1, i+ 或 +i, 而不是任何组合, 参见问题。有人说 i=i+ 的行为是未定义的, 但是我刚在一个兼容 ANSI 的编译器上测试, 得到 了我希望的结果。面对未定义行为的时候, 包括范围内的实现定义行为和未确定行 为, 编译器可以做任何实现, 其中也包括你所有期望的结果。但是依靠这个 实现却不明智。参加问题,和。使用我的编译器,下面的代码 int i=7; printf(%dn, i+ * i+); 返回 49 不管按 什么顺序计算, 难道不该打印出56吗?尽管后缀自加和后缀自减操作符 + 和-在输出其旧值之后才会执行运算,但这里的 之后常常被误解。没有任何保证确保自增或自减会在 输出变量原值之后和对表达式的其它部分进行计算之前立即进行。也不能保 证变量的更新会在表达式 完成(按照ANSI C的术语,在下一个 序列 点 之前, 参见问题 之前的某个时刻进行。本例中, 编译器选择使用变量的 旧值相乘以后再对二者进行自增运算。包含多个不确定的副作用的代码的行为总是被认为未定义。(简单 而言, 多个不确定副作用 是指在同一个表达式中使用导致同一对象修改 两次或修改以后又被引用的自增, 自减和赋值操作符的任何组合。这是一个 粗略的定义; 严格的定义参见问题, 未定义 的含义参见问题。) 甚至都 不要试图探究这些东西在你的编译器中是如何实现的 (这与许多 C 教科书 上的弱智练习正好相反); 正如 K&R 明智地指出, 如果你不知道它们 在不同的机器上如何实现, 这样的无知可能恰恰会有助于保护你。以(i为例作为自增自减的变量)一、在C语言中,是以整条语句为基础的。1、先计算完所有的(+i )和(一i),得出这个时候的i值。2、再根据现在的i值计算整条语句的值。3、最后再根据(i+)和(i)计算出i的值。例(1):int i=5,k;k=(+i)*(-i)*(-i);printf(k=%d i=%d,k,i);以上程序的输出结果为:k=64 i=4。先计算(+i)、(一i)、(_i)的值,得出i=4,在算k=i*i*i,得出k=64。例(2):in t i=3,k;k=(+i)*(i-)*(-i);printf(k=%d i=%d ,k,i);以上程序的输出结果为:k=27 i=2。先计算(+i)、(-i)的值,得出i=3,在算k=i*i*i,得出k=27。最后算()doc矽萊单”I羌准词语诰鉅尊耳翡针自臥自宛运鼻在c语言申自iiu自减运算符的使用非檔灵活,便用它衍 可wflts序简洁褪:n执行效事提高,但是在使用自如自*运 算符时”必烦打好基本功.它的作用是宴现整型我指针变址增1 或诚】操作貝律应用时还涉及到前自增自减运算和后自埔自 减运算而这两种运鼻的结果又会大贰一祥,使用时一定要十分 小心*首先自環自减运算只适合于针变量(図只這 合于左值谖算儿而不BE对常童科表达式进行自增自减运算.ft 容為出冋题的是自增自减运算符与加减运算符的混合运算和,4自堵自减运算符与加减运算符的視合运算自加、自减运算符+ +和一一的柞用是使聋*的牯増 1或减1m + +和 的结舍方向是自右至左灯如:对于*inug,b广的变豪定文十有下列表达式:b -bd-a+ + 十血十 +十凰申”bft十+ +亘+ + 十n对于.*SSx然后将自增后的值相加*即b =C-F+a) + il Ce = FC h V 从數学的箱度,这彳 虑后会发現18设输入导 假人然后计算0V = h - 2值为 1(%:,I 密合题童,所以醫话语冷 Uli + + 三、逻St运拿左C语言中广奁僅 劉的绪果下问题值=0 计算在逻辑表达式的; 运算对彖部分 对象的值,这样可以提需对象僅为O.HJ不再对右 定嚣X若丨|”的左运芻 因整个式子的结果必定 例如求表达式|VI护的优先级而先求b? 边的若上为菲0爲四第字符数组就艰C谱盲中有赋值廷 常量、变、喪达式或函7C 程序中自增(自减)运算的研究与分析李茂秋1助理研究员,泰山学院计算机科学系 (271021),摘 要:自增(自减)运算是C语言教学中的难点和重点,大多C语言教材 回避了这个繁琐的问题,给C语言的学习增加了难度,本文作者在引用大量例程 和上机实验的基础上,详细分析和讨论了 C语言自增(自减)运算符的运算规则, 提出了自己的见解,对C语言学习者具有一定的启发和借鉴作用。关键词:C语言 自增运算(符)自减运算(符) 自增(自减)因式引言C语言具有丰富的运算符,用以实现丰富的运算功能,同时,其丰 富的运算符又具有繁杂的运算规则,比如:优先级、结合方向等。正确的理解和 使用这些运算符,能给程序设计带来效率高、代码简单等好处,自增(自减)运 算符是C语言中语法繁杂、运用灵活的一个运算符,在C语言的学习中,一直是 一个难点和重点,在历年的等级考试中,占有较大的比重,但在各种C语言教材 中,很少对此进行详细细致的介绍。此外,在实际编程实践中,a+尽管和a=a+1 都具有对a赋值的作用,但a+具有一个显著的优点就是,它比a=a+1要快,占 用的RAM更少,原因是它们的指令执行周期不同,产生的目标代码(机器码)不 同。因此,对+运算符的详细介绍十分必要,笔者结合多年的C语言教学和开发 实践,引用例程,拟对此进行分析、讨论与总结。一、自增(自减)运算符的基本理论在自反赋值运算符中,有两种特殊的情况,也是两种极为常用的操作,即 k=k+1写作k+=1,k=k-1写作k-=1。这两种运算符对k所进行的操作是增1(或 减1)的操作,通常,我们把k当作计数器,这两个运算符通常用来对计数器进 行控制,用来记录完成某项任务的次数,C语言为这两种操作提供了更为简洁的 运算符:k+或+k (k_或_k);+k/k称为前缀形式;k+/k一称为后缀形式。无论前缀还是后缀的形式,都是使运算对象自身增1 (减1 ) 。因此,称+ (_) 自增(自减)运算符。自增(自减)运算符的优先级是14,级别较高,仅次于括号、方括号等, 其结合方向是“自右至左”。关于结合方向,将在后面说明。自增(自减)运算符的前缀和后缀形式,在表达式中,有着不同的值,这将 是我们在本文讨论的主要方面。尽管自增(自减)运算与自反赋值运算具有相同的赋值效果,但应当知道, 他们是不同的运算符,因为它们的优先级不一样,究其原因是,其编译后的目标 代码不同,指令的执行周期不同,自增(自减)的执行周期小,速度快,效率高。因为自增(自减)运算是一种赋值运算,因此不能对常量或表达式进行自增(自减)运算。二、自增(自减)运算符的几种使用环境及其运算规律 研究为了研究的方便,我们把出现在表达式中,或独立构成语句的一个自增(自 减)运算式,称作是一个自增(自减)因式。对于自增或自减运算,我们除了关 心自增(自减)的效率外,更重要的,我们关心的是自增(自减)因式的前缀和 后缀两种形式,所产生的因式的值,及运算对象(变量)的值。这是C语言学习 和教学中的难点,也是C语言水平考试中常见的考点。大体说来,应当考虑以下几种使用情况:1一个自增(自减)因式构成一个独立语句。形如:k+;或+k;这样一个因式构成一个独立语句时,其前缀形式和后缀形式得到的结果是一 样的,即得到的因式的值一样,参与运算的变量k的值一样。例程1: /*/main()int k;k=1;k+;/*前缀形式*/printf(“nk=%d”,k);/*验证前缀形式得到的k值*/k=1;+k;/*后缀形式*/printf(“nk=%d”,k);/*验证后缀形式得到的k值*/程序中,初值为1的变量k,分别出现在前缀和后缀两种形式的自增运算独 立语句中,语句执行的结果,使k值都增加为1。实际上,两个因式的值都是2。因此可以说,在自增(自减)运算构成独立语句的时候,对自增(自减)运 算的前缀和后缀的区分是毫无意义的。2在表达式中引用同一个变量的一个或多个自增(自减)因式。(1) 在表达式中只含有一个自增(自减)因式,但表达式不 仅仅包含此因式,还有其他运算对象或运算符。这种情况,按照各种教材所讲授的规律:表达式引用此因式时,如是后缀形 式,则先引用变量的值(未变化的值)当作此因式的值,参与表达式的运算,然 后再变化(自增或自减)变量的值,变化了的变量的值不参与表达式的运算。如 果是前缀形式,则先进行变量的自增(自减)运算,然后引用变化了的变量值, 参与表达式的运算。例程2: /*/main()int k,j;k=5;j=k+; /* 前缀形式的自增运算出现在赋值运算中*/printf(“(1)k=%d,j=%dn”,k,j);k=5;j=+k; /* 前缀形式的自增运算出现在赋值运算中*/printf(“(2)k=%d,+k=%dn”,k,j); /*验证前缀形式的运算对象和因式 的值*/程序的运行结果是:(1)k=6,j=5; /*先把k的初值5拿来用,即赋给变量j.再改变k的初值 */(2)k=6,j=6;/*先完成对k的自增为6,再拿来用,即赋给变量j.*/因此,这种情况下,应该描述为;当一个自增或自减运算出现在表达式中整 体参与运算时,应遵循后缀形式;先用后变,前缀形式;先变后用的原 则。2)表达式中含有两个或两个以上的自增(自减)运算因式。实际上,当多个自加(自减)运算出现在同一个表达式中,系统所进行的运 算远没有一个自增(自减)运算因式时简单。请看如下例程:例程3/*/main()int a,k=4,k1,k2,k3,k4;a=(k1=k+)+(k2=k+)+(k3=+k)+(k4=k+);printf(a=%d,k=%dn,a,k);printf(k1=%d,k2=%d,k3=%d,k4=%dn,k1,k2,k3,k4); 运行结果:a=20,k=8k1=5,k2=5,k3=5,k4=5程序的运行结果说明;参与表达式运算的同一个变量的自增(自减)运算因 式,在表达式中具有相同的结果,而参与自增(自减)的变量k的最终结果与这 些因式的结果并不完全一致。通过大量例程我们可以得到如下的结论:对于参与表达式运算的各个自增(自减)因式来说,最终的值是一样的,我 们可以这样解释其过程:C系统对参与表达式运算的多个自增(自减)因式,按 照运算的优先级,逐一进行运算扫描,扫描的过程遵循前缀和后缀的规律,并将 最后运算的自增(自减)运算因式的结果带回到各个自增(自减)因式,使得各 个自增(自减)因式以相同的值参与表达式的运算。在上述例程中,k1=k+,按照后缀的规律,先引用k的值,再增加1,使得 k仁k+的值暂时为4,计算k2=k+时,没有使k的值增1,而是继续引用 k=4,k2二k+的值仍然暂时为4,计算k3=+k时,引用k的当前值k=4,因是前缀 形式,所以,先增后引,使得k3=k+的值暂时为5,在计算k4=k+时,同理, 引用k的当前值k=5,因是后缀形式,k4=k+的仍为5。C系统把这最后一个自 增(自减)运算因式的值,重新带回到其他自增(自减)运算因式,参与表达式 的运算,因此使得k1=5,k2=5,k3=5,k4=5。为验证一下这个结论,我们可以随意 将程序中的各自增(自减)因式修改,改变前后缀形式,改变增或减,均可以分 析得出正确的执行结果。对于这种结论,我们可以概括总结为一句话:对于表达 式中同一变量的多个自增(自减)因式的值,遵循“逐一扫描,共同引用”的规律。上述例程3还说明,对于参与自增(自减)运算的变量来说,其最终结果的 得出:把该变量的各个自增(自减)运算因式,等价于一条一条的自增(自减) 语句,按顺序执行(不考虑其前缀或后缀形式)后,即得到改变量的最终结果。 例如上述例题中,k的最终结果实际上一下语句顺序执行的结果: k=4;k+;k+;+k;k+;。关于以上分析,我们可以用以下例程再次加以验证,请读者依照上述规律说 明加以分析:例程4: /*/main() int a,k=4,k1,k2,k3,k4;a=(k1=k+)+(k2=k-)+(k3=k+)+(k4=k+);printf(a=%d,k=%dn,a,k);printf(k1=%d,k2=%d,k3=%d,k4=%dn,k1,k2,k3,k4); 程序运行结果:a=16,k=6k1=4,k2=4,k3=4,k4=43 含有多个自增(自减)因式的表达式当作函数参数时的情形在pri ntf ()函数中,要输出一个含有多个自增(自减)因式的表达式的值, 此时,尽管多个自增(自减)因式出现在一个表达式中,但由于是在printf() 函数中,其运算的规律稍有变化。请看如下例程:例程 5: ma in()int a,k=4,k1,k2,k3,k4; printf(a=%d,k=%dn,a=(k1=k+)+(k2=k-)+(k3=k+)+(k4=k+),k);printf(k1=%d,k2=%d,k3=%d,k4=%dn,k1,k2,k3,k4); 程序运行结果:a=18,k=4上述例程中,printf ()函数中的输出对象,虽然也是一个表达式,并且含 有多个自增(自减)运算因式,但各因式值的分析与表达式语句中有所不同,我 们通过程序的运行结果可以看到,输出的表达式的各因式,其值依赖于当前的k 值,当前k值的求得,不仅与自增(自减)运算的前后缀形式有关,而且也与上 一个运算的自增自减因式的k有关。实际上,在pri ntf()函数中输出的表达式 中,多个自增(自减)因式,相当于多个自增(自减)语句,C系统按照优先级 的先后顺序,依次执行,依次求得各因式中的k值和因式的值,并立即将这个因 式的值用于整个表达式的运算中,而不像上述例程3与例程4那样,将最后一个 因式的值带回到前面的各因式。实验证明:当用其它函数进行同样的试验时,得出的结论是一样的,因此, 我们可以把上述试验结论推广为含有多个自增(自减)因式的表达式当作函数参 数的情形。另外需要注意:在C程序中,函数含有多个参数时,其参数的运算顺序是自 右向左,而不是等价于逗号表达式。比如:k=4; pri ntf(” d,%d”,(k+) + (+k) + (+k),k=5);应按照 k=5 初始值进行分析。4含有自增(自减)的表达式被宏替换的情形。含有自增(自减)的表达式被宏替换也是经常遇到的情形,这种情况宏题如果 出现在表达式中,就按照表达式情形下的规律,如果是当作函数的参数,就按照 函数参数的情形下的规律进行运算,换句话说,宏替换并不影响表达式的执行。 因为宏替换本身不具有运算功能。例程6 :/*/#include#define M i+#define N +imain()int k,i,j;i=4;j=(i+)+(+i)+(i+); /*不引用宏替换的情形*/printf(%d,j);printf(,%dn,i);j=M+N+M; /*引用宏替换的情形*/printf(%d,j);printf(,%dn,i);程序运行结果:15,715,7三、使用自增(自减)运算应注意的其它事项:1自增(自减)运算符与其它运算符同时出现时,要注意结 合性。自增(自减)运算符是一个单目运算符,使用时要注意其结合方向为自右而 左,以下两种情况需要注意:(1) 如:int p; p+;此时对于同一个运算对象p来说,先进行间接云 算“*”呢还是先进行p+运算呢应当考虑*和+的优先级相同,但都是单目运算 符,应遵循自右向左的结合性,所以,p先与右边的运算符+结合,在进行间接 运算,即等价于:* (p+);(2) 如:k+k;此时,应当认为是(k+)+k还是k+ (+k);呢C编译系统 在处理这些运算式,遵循的规律是:尽可能多的自左至右将若干个字符组成一个 运算符。依照这个规律,k+k应等价于:(k+) +k;这种使用方法尽管在语 法上没有错误,但给我们阅读和分析程序带来了不必要的麻烦,因此建议读者不 要使用这种方法。2自增(自减)运算是一个表达式,不能进行赋值运算。在C等级考试中,常常出现+k+,k+,k+=2,+k=3等形式的写法,关于 以上写法,要把握一点:自增(自减)运算式,其本身是一个表达式,不能被赋 值。因此上述四种写法中,只有+k=3是合法的。说明:C语言由于自身的开放性,各种不同版本的编译系统,可能由不同 的细节上的差别。以上文中各例程均在编译环境中编译,并正确执行。参考书目:1. 谭浩强 C 程序设计 北京:清华大学出版社,1999 年2. 教育部考试中心二级教程一C语言程序设计北京:高等教育出 版社,1998年
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 办公文档 > 模板表格


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!