浅析C语言自增自减运算符的使用
2010-01-23夏超群
夏超群
(武汉工程职业技术学院江北校区 湖北 武汉:430415)
C语言的运算符非常丰富,在程序中可以灵活使用它们以达到所需的功能。许多初学者学习使用过程中,经常对自增、自减运算符的运算结果产生质疑,弄懂自增、自减运算符的运算,显得至关重要。
1 自增、自减运算符的特点
1.1 自增运算符 ++
它是单目运算符,其功能是使操作数的值增1。其操作数必须为变量,++可以置于操作数前面,也可以放在后面。例如:
++n ;n++ ;
这两个语句执行的结果都是使变量n的值增加1,单纯从这两个语句的执行结果上看++前置和后置似乎没有区别,它们和下面的赋值语句得到的效果也是一样:
n=n+1;
但我们不应该被表象迷惑,实际上,++前置和后置是有区别的,具体如下:
n++:先使用n的值,再使n值增加1。
++n:先使n值增加1,再使用n的值(使用时n的值已经增加了)。
例如:int n=1,p,q;
p=n++;q=++n;
对于“p=n++;”这个语句,是先使用n的值,将其赋给p,再使n的值增加1。即该语句等价于这样两条语句:p=n;n=n+1;所以这个语句执行完后,p的值是1,而n的值变成2。对于“q=++n;”这个语句,是先使n的值增加1,再将n的值赋给q。即该语句等价于这样两条语句:n=n+1;q=n;所以这个语句执行完后,n的值变为3,而q的值也是3。
无论前置还是后置,++都会使其操作数的值增1。不同的是,++前置(如++n)时,自增表达式的值等于其操作数自增后的值;++后置(如n++)时,自增表达式的值等于其操作数自增前的值。
例如:int n=5,p=0,q=0;
q=++n+q;//该语句执行后q为6,n为6
n=5;
p=n+++p;//该语句执行后p为5,n为6
上例中,表达式++n的值等于n自增后的值,即6,所以q最后得到的值为6。表达式n++的值等于n自增前的值,即5,所以p最后得到的值为5。
1.2 自减运算符 --
自减运算符的功能及应用类似于自增运算符, --的操作数也必须为变量。--可置于操作数前面,也可置于操作数后面。区别只在于自减运算符使操作数的值减1,而自增运算符使操作数的值增1。具体如下:
--n:先使n值减1,再使用n的值(使用时n的值已经减少了)。
例如:int n=5,p=0,q=0;
q=--n+q;//该语句执行后q为4,n为4
n=5;
p=n--+p;//该语句执行后p为5,n为4
不管是自增还是自减,前置运算符是“先变后用”,如++n或--n,执行后表达式的值和变量n的值相同;而后置运算符是“先用后变”,如n++或n--,执行后表达式的值和变量n的值不同。
Android系统中含有很多涉及获取用户隐私的API(Sources点)以及隐秘的数据发送途径(Sinks点),通过归类整理并使用基于过程间数据流分析技术[5]的污点传播算法,寻找从Sources点到Sinks点的传播路径,从而发现这些隐私泄露问题。
1.3 优先级
自增运算符和自减运算符的优先级比+-*/的优先级要高。因此“n*m++”表示“n*(m+ +)”,而不是“(n*m)++”。而且“(n*m)++”是错误的使用方式。因为++和--的操作数只能是变量,不能是表达式或常量,而“n*m”是表达式。
注意,不要把优先级和运算顺序混淆了。
例如:int x=1,y=2,z;
z=(x+y++)*3;//该语句执行后z值为9, y值为3
用数字代替上面的语句得:z=(1+2)*3;
优先级表明的是++作用于y,而不是(x+y),但它决定不了y的值何时增1。我们可以肯定的是,在整个语句执行完毕后,y的值肯定增加了。但是,我们不知道该语句执行中的什么时候,y的值会增1,这是由编译器决定的。
2 自增、自减运算符的应用
C语言表达式的应用非常灵活,这种灵活性可使C程序简洁,但同时也会引起副作用:使程序费解,分析程序时易于发生误解或错误。而且C语言发展至今,不同的软硬件环境有不同版本的编译软件,对同一个C的源程序,不同软硬件环境、不同的编辑编译软件处理的结果不同。由于现在一般都是使用图形界面的操作系统,使用的编译软件也是简单直观的图形界面为主,下面以VC++6.0环境C程序中自增、自减运算符的应用来进行详细分析。
例1:分析下面程序运行后的输出
分析:由于单目运算符的优先级高于双目运算符,而且自增自减运算符的结合性是自右至左的,所以程序的4、6、8行的语句分别等价于:a=(++b)+ (c--);a=(b--)-c;a=-(b++)+c;我们前面说过自增自减符前置时是“先变后用”,执行后表达式的值和变量的值相同;后置时是“先用后变”,执行后表达式的值和变量n的值不同。
由此分析知:第4行语句执行情况为:表达式+ +b的值为6,变量b的值为6;表达式c--的值为5,变量c的值为4;所以a=6+5。
同理,第6行语句执行情况为:表达式b--的值为6,变量b的值为5;所以a=6-4。第8行语句执行情况为:表达式b++的值为5,变量b的值为6;所以a=-5+4。所以程序运行的输出如图1所示。
图1 例1在VC++6.0下的运行结果
例2:分析下面程序运行后的输出
分析:该例4、5行语句中各有若干个自增表达式,从理论上分析第4行语句中表达式(i++)+(i+ +)+(i++)的值应为5+6+7,实际却是不论何种编译器执行结果都是5+5+5,这说明后置自增自减运算符的“先用后变”的“变”是指在下一条语句执行前统一改变,而不是刚用完就变,故第4行语句等价于:p=i+i+i;i=i+1;i=i+1;i=i+1;
第5行语句执行结果和所用的编译器有关,由于我们前面已经说明在VC++6.0环境下分析运算符运算结果,因此该语句等价于:j=j+1;j=j+1; q=j+j;j=j+1;q=q+j;
造成这种结果是因为高级语言的一条语句经编译解释成若干条机器指令,这若干条机器指令的顺序最终决定该等价高级语言语句的执行结果。
该例是教学时所用教材上的实例,教材上分析认为运行输出如图2所示,教材上并未说明该结果是在何编辑环境下的输出。我校机房运行调试C程序用的是VC++6.0,为了让学生能理解运行环境对结果的影响,我特意让学生上机运行这个程序,结果输出如图3所示。
图2 例2在TC下的编译输出
图3 例2在VC++6.0下的编译输出
为了让学生分析该例第5行为什么会得到非预期或者说与教材不同的结果,将该例代码稍作修改后以c1.c为文件名保存,同时为学生提供不同的编辑编译环境,让学生分别在不同编译环境中调试运行该程序,并分析得到这种运行结果的原因。通过自己动手上机调试分析,学生很容易理解自增、自减运算符前后置时运行结果为何不同。
文件名为c1.c的源代码如下:
例3:分析下程序运行后的输出。
分析:由上两个程序的分析知:后置自增或自减运算符时,自增或自减变量值是在本语句执行后,下一语句执行前改变。因此有:表达式x++的值为17 (先用),表达式—y的值为4,y值也为4,17/4结果取整为4,x=17*4。第4行语句执行后再执行表达式x++的变(后变),程序的运行结果如图4所示。
图4 例3在VC++6.0下的编译输出
3 结束语
C语言运算符的灵活应用可能会让初学者对程序造成误解,甚至不明白程序为何得到此种结果。学习程序关键在于多分析、多设计程序,程序的运行一定会遵循某一规律。而对于自增自减运算符来说,都知道运算符后置时是先用后变,但相关变量的值何时变才是关键,要明白这一点,就需要在实践中理解掌握。如果通过实践明白的先用后变的“变”是在下一语句执行前进行的,那么再错综复杂的运算符的应用,分析它的运算结果也得心应手了。
[1] 谭浩强.C程序设计[M].北京:清华大学出版社.
[2] 阳晓霞,刘清华.C语言教学探讨——易造成学生困惑的几种运算符[J].福建电脑,2007,(11):212-214.
[3] 吴 琼.C语言运算符的结合性分析[J].电脑知识与技术, 2007,(2):463-464.