ok,那么关于算数运算符啊,我们讲差不多了。
只剩下最后一点点。这一点点呢还挺麻烦。
这一点点就是加加减减运算,
也就是自增自减运算。那当然对这个运算呢,
并不陌生。比方说,i加加这个词, 经常出现在哪里啊?
出现在for循环里面,对吧。我们用它来对i进行i自加的运算,
这个运算我们讲过,i加加就等于i加1.这两个,
这两个的意思是一样的。那么,除了i加加,
运算之外啊,在c语言里面还有一种运算叫加加i。 加加i,也是对i进行加1的运算.
那有同学就问了,它也是对i进行加1的运算,它也是对i进行加1的运算,
那两者之间有什么区别呢?区别在这里,加加i
加加号如果写在前面的话,那么表示
在使用i之前,先把i的值, 加一下,
加1或者是减1,如果是减减的话那就是减1.
i加加的意思呢,是说在使用i之后,
再把i的值再加1或者减1。
有同学可能听不懂,什么叫使用之前,什么叫使用之后啊?
我给你举个例子你就明白了。比方说啊,我们把这个i比作一本书,
这本书呢,是我们从图书馆给它借来的。所谓加加i,
也就是在使用i之前进行加1是指的什么意思呢?
在你借出这本书之前,你还没看呢,你先给这本书
包一个书皮,给它加上一页,这是加加i的
一个运算。那么i加加的运算是什么意思呢?
是说当你把这本书借出来,并且你读完了以后,
你准备要把它还回图书馆去之前,你给它包了一个
书皮。这就是i加加的一个运算。 这是,这两个不同的运算。
那有的同学说,这样说啊,我还是不明白,听不懂。ok,没关系,我们来举个例子,
你就清楚了。例如,i的值啊,现在是3。在i是3的情况下,
我们呢,做四个运算。
我们看看,分别做完这四个运算,i的值,j的值,以及打印出来的值分别是多少。
比方说,当i等于3的时候,我现在做一个运算, j等于加加i。
那么当i等于3的时候,做完这个运算,请问j的值等于多少?i的值等于多少?
毫无疑问,在这个式子里头啊,我们做了一次加加i,所以说做完
这个式子以后,i的值等于多少?i的值一定等于4.那么j的值等于多少呢?
想想我们刚才说的话。加加i,加加i相当于
你把i借出来,先给它加1,先包书皮,
然后再去用,再去读这本书,再去用这个i。
所谓用这个i,就是用i给j进行赋值,也就是是说,当j
获得这个值的时候,是i加加以后得到的那个结果。也就是说,包了书皮的那个i。
也就是说,这个时候j必定等于4。那么我们相反再看一个结果,
如果i等于3,现在我们做的运算是j等于i加加,加加跑到后面去了。
也就意味着,我们拿出i了以后,我们先要去读它,先要去做事情,
先拿着这个i给j,
先把i给j,然后我们再给i包书皮加1,
对不对?所以说,运算完了之后i等于多少啊?
i等于4。j等于多少呢?j等于3。因为i在没包书皮的时候,就已经
给了j了。
我们再往下看,当i等于
3的时候,我打印一个值,叫做cout加加i, 我相信这次,大家应该是比较明确的了。
我先拿出i来,一借出这本书来,我就先给它包一个书皮,然后
再去用这本书,所以说这个地方应该打印等于多少啊?3加1先等于4,先把它打出来。
一定是这样的。那再看后面这个,当i
等于3的时候,如果执行cout i加加,它会打印出多少来呢?
先把i拿过来先用,用完了以后再去包书皮。用,
所谓的用就是把它打印出来,所以这个地方会打印出3来。打印完了之后,这个i等于多少啊?
i等于4,这就是i加加和加加i的区别。
那么这个例子呢还是比较,相对比较简单的。
我们再来看一个稍微难一点的例子。当然,我先说明,
对于i加加和加加i,我们在考试里面,绝对不难为,拿这个东西
去难为大家。我们没有针对这个东西的考题,但是 这个事情大家应该掌握。
可是呢,又不需要彻底的掌握。为什么呢?后面我再去解释。
那么,这几个例子,还是需要大家掌握的。我们再来看一个例子,看这个例子。还是
i当前的值假设是3,请问
下面的几个执行结果。现在呢,稍微加了一点难度。
第一句,叫cout 减i加加,打印这句话。看到这句话的时候啊,我们立刻要有一个警惕性,
在这句话里面,虽然非常非常短,
但是出现了两个运算符。一个是负号,
符号运算符;一个是加加号,加加运算符。为了搞清楚
到最后这个结果到底是什么,我们必须要首先清楚的一件事情就是,
这两个运算符好,哪个运算符号是先进行计算,
也就是说,先解决运算符优先级的问题。 当看到这个式子的话,大家第一反应最好是
找一本书,先去查一下运算符优先级,
到底这个它的优先级哪个是高的,哪个是低的。
查一下c加加的运算符我们就知道,对于放在后面 的,也就是说所谓的后置的加加号,
它的运算符优先级,它要高于负号。
所以说,别看这个符,这个表达式非常的简单,它包含了
两个运算符号,而且这两个运算符号优先级不同,
这就像有两个指挥官一样,有两个指挥官在这,谁的优先级高我们先听谁的。
有一个指挥官叫做加加号,另一个指挥官叫做负号,毫无疑问我们要先听加加号的。
先听加加号,于是呢,加加号这个指挥官就下命令了,说
你们使用完i的话,你再对i进行加1,
这就是加加号这个指挥官所下达的命令。他说你先去用,用完了
给我加1,ok。我们拿了这个命令之后,
再去找负号。负号呢说ok,那我现在 就是要对它进行,原来是正的,变成负的,原来是3,我把它变成
负3.然后打印输出。打印输出用完了没?用完了。
这个时候,最开始加加号给我们的那个命令,我们应该去执行了。
等用完了以后,把这个i再进行加加运算,所以说整个这个式子会打印出来多少?会打印出来负3.
同时,i的值会变成4.有的同学说,啊呀李老师不对呀,人家是i加加呀。
i加加是,优先级是高的,
你怎么先,按照负号先算。算完了之后再给它加加呀。
没错,它的优先级的确是高了,但是
它是我们的大领导啊,我们的大领导给的命令是什么呢?
先拿去用,用完之后回来再加。那我们听不听他的? 当然要听。这就是整个这个式子的含义。
那么再看一下,当i等于3的情况下,如果我们打印的是负号,然后加加i,
如果是这样的话,应该怎么办呢?我们迅速的再去查一下
运算符优先级。经查,我们可以看到 减号和加加号,实际上它们的运算符是
同级的,优先级是相同的。但是,类似于这样
同级的运算符来说,是遵循右结合,也就是说
要先算右边,然后再算减号。
是这样的一个计算顺序,所以说对于式子而言,我们仍然要先算
加加号,然后再算这个负号。那么ok了,这个比较容易。
i等于3的时候,我先算加加号,那,那意味着什么啊?我一拿出i来,
我就先对i进行加1的运算。对吧,一借出i来,我先给它包书皮, ok,那我就,i就变成了4,
对不对?所以说,如果这个式子打印出来的话,将打印负4,最终i的结果呢,也等于4.
这是这个结果。ok,我们继续往下看。
第三个式子。第三个式子啊,是我们在, 在跟大家讨论的过程中,同学们赠给我的一个例子。
说,李老师你不是说,那这个里头,是先t加加的吗?
我现在就非要让它这么来做一下,
先把负i 给它括起来,然后再算加加,
可以吗?我的回答是,不可以。为什么呢,编译错误。
为什么会编译错误呢?因为加加号只能
用于变量,不能用于表达式。什么意思呢?对于一个变量,
比方说i,我们写i加加,或者是加加i,
是可以的。这就意味着这个加加号啊,我们给它用的变量i身上,这是没有任何问题的。
但是,不能把这个加加号, 或者前置,或者后置,任何一个加加号都不能用到表达式身上。
你比方说我们来写这样一个表达式,i加j,括起来,加加,
这个呢,编译就是错的,为什么编译错的?因为加加号
不能用于表达式,i加j是一个表达式。
同理同理,在这,用符号括起来的这个负i,
仍然是一个表达式,我们不能把这个加加号用在一个表达式身上,
这就错了。ok,所以说第三个,编译错误。
那有的又有人问,第四个呢?我如果这么写呢,加加i加加。
ok,这个式,这个式子,在某些语言里头,
是成立的。首先说,这个式子,cout加加i加加,在某些语言里头成立。
but在c语言里头,它不成立。
原因是什么呢?原因跟上面一样,加加号不能用于表达式。
我们来分析一下这个句子,加加i加加这里头,别看它简单,
也是两个运算符,一个运算符是前置的加加号,一个运算符是后置的加加号。
那么你去查一下运算符的优先及顺序,我们就会发现
后置的加加号要先于,优先级要高于前置的加加号。
所以对于这样一个表达式而言,要先算i加加,然后再把这个结果,
再进行加加运算。如果能计算的话,因为按照这种顺序去算,但是
算i加加没问题,但是如果你想对i加加进行
加加的运算,那就错了,因为加加号不能用于
后面是一个表达式,不能用于后面的表达式。
这就是所谓的原因。 那么说到这呢,我觉得可能我们对于加加号啊,理解就更深入了一层。
那么我们做一个总结,其实在这,没有太多的东西,做一个总结。 加加,或者是减减,
只能用于变量,而不能用于表达式。接下来呢我们再做一点
说明。关于加加i或者是i加加啊,我们可以写出非常非常复杂的表达式来,
甚至于呢,对于某些表达式而言,在不同的编译系底下,会有不同的计算结果,所以说我们没办法一概而论。
但是呢,有一些常用的情况,我们必须cover到。
必须覆盖了,我们再举一个例子,也是一个稍微常用一些的
情况。ok,那么关于自增自减运算,我们
再多介绍一点,那就是,当把自增自减的运算,跟输出放在
一起的时候,那么这种情况呢,是大家需要特别注意的,所以说呢,在这呢,我们再
讲解一下。我们可以看这个程序,在这个程序里头啊,我定义了6个变量,分别是a,
b,c,d,e,f,然后呢,底下
我以不同的方式,那这几个变量啊,打印出来,看看打印的结果
会是怎样的,我们来分析一下。第一个我先打印a, 先打印a,然后空格,
a加加,空格。我们先来想象一下第一句输出的结果会是怎样的。
那么很多同学就说,因为a的初始值是0嘛,而且,这里写的是a加加,那就意味着要
用完了a之后,再加1。那所以说,在这个地方,打印出来的结果应该是00。
然后打印完了之后,a的值应该是1,应该是这样的一个结果。
是吗?我们来看一下它的输出结果。
并不是这样的,它的输出结果是10。 为什么是这样的一个结果呢?
那么我们来分析一下这条语句,看它的结果为什么是
10呢?其实有一条规则特别要告诉大家。
那么在告诉大家之前呢,我先要强调一下,可能在不同的编译系底下,会有不同的输出。
那么在visual c加加底下,是这样的。对于一条输出语句,如果这条输出语句
里面包含了多个表达式,那么程序,在打印这些表达式的值的时候,
它是最优先计算最右侧表达式的值,
然后再计算左侧表达式的值。也就是说,
它是按照一条从右往左的顺序,
来分别计算这些表达式的值的。
在一个输出里头,从右往左的顺序,
这是在VC下面,大家一定一定要注意这件事情。
那么既然知道了这个,我们就好计算了。我们看一下,
既然是从右往左,那么一开始a的值是0,所以在这,应该打印输出0.
然后打印完了以后, 立刻a的值就进行加加的处理,
所以说,a的值等到再去打印这个表达式的值的时候, 那么a的值是多少啊?a的值是1.
所以呢,会在这打印1,会在这打印0. 所以会出现这样的结果。
ok知道了这个之后啊,我们也就好办了,再去看第二个。b的值一开始也等于0,
然后呢我们先去计算它,b加加,那么在这毫无疑问,也会打印0.
打印完了0以后呢,b加加起作用了,因为是先用再加加。
加加完了之后,b变成1,也就是说,b到这的时候先变成1,因为呢,
在这又出现了一个加加,而且是先加加。那就意味着,
我在用之前就要对这个b进行加加。于是,这个地方,b就变成了2.
2,所以说,第二行会打印输出20.
我们再来看第三行。第三行,它会首先计算这个表达式的值,这个表达式稍微有点复杂,
在这个表达式里头呢,既出现了c加加,又出现了加加c,还出现了一个加号。
那这个怎么计算呢?那么,在vc底下,它是
这样来计算的。既然这个表达式里面出现了加加c,
那么我首先把c取出来的时候,我就首先完成这个加加c的运算。
因为这是一整个表达式,在这个表达式里头只要出现了c,加加c,
出现了几个,我就先给c加几次,也就是说,c一开始
是2,那么我就先对这个c进行一个加加的运算,
然后呢,把这个3,代入到这个表达式里头,让它进行
计算。c加加,因为这个加加出现在后面,所以要等到用完了
才能进行加加。所以整个表达式是这样来进行计算的。3,这个地方也是3.
3加3等于6,这个地方输出6。
输出完了以后,c的值后再加1,c的值会变成4.
所以说,c会在这输出4.
所以整个这条语句的输出是4,
6,这是在visual c加加下面的输出。是这样的,这是第三条语句。
我们再看第四条语句。 那么在这个表达式里头呢,既出现了负值,又出现了加号。我们来分析一下。
那么面对这样一个表达式呢,我们会先计算这部分的值,然后呢我们计算
后面这部分的值,最后我们计算这个加号加起来的值。这是这个
计算顺序。那么在计算开始的时候呢,
f等于2,d等于f加加。那既然这个加号是在后面,
所以说,先赋值,再加加,那么d呢,就被赋值为2,d被赋值为2。
那么接下来,这个f是要等到,这个加号算完了以后再加加呢,
还是计算完这个小括号里面的,
赋完值以后就加加呢?
在vc里面,它要等到这个加号算完以后,统一再进行
后置的加加的运算。所以说在这,
所以在这,那个f呢,赋值的时候,这个f仍然是2,
仍然是2,给e赋的值呢,也是2,
也是2.所以说,整个这个表达式的值是多少啊?
既然赋的值都是2,所以整个这个表达式的值是4.
那么在这打印4.那么再往下看,打印完4以后呢,我们再把f打印出来。
当然毫无疑问,因为在这f呢,原来是2,经过了一次加加,这个地方会打印出3.
然后呢,d的值,刚才我们分析过,它依然是等于2的。
e的值呢,也等于2. 这就是最终的一个结果,它会打印出10,20,
46,4,322.我们来看一下这个结果是不是这样的。
它确实是这样的。10,20,46,4,322.
这就是当把加加,减减,也就是自增自减运算跟输出放在一起的时候,
所遇到的这个情况。 当然我们还可以构造更复杂的
加加或者减减的运算。但是呢,在这我们就不再作探讨了。
那么,如果有的同学对这个问题非常的
感兴趣,那怎么办呢?我还真的需要提示你一点。 为什么呢?因为关于加加减减的运算,
资料不是特别好找。网上呢,众说纷纭。
其实有一个非常非常好的办法去判定, 这个运算到底是怎么进行的。
那么就是,你把你想要检测的加加
或者减减的运算,写成一个表达式,放在程序里面,
然后对这个程序插入一个断点,进行debug,
在debug的过程中,你可以看到这个程序反编译的结果。
那么在程序反编译的这个结果里面, 那么用汇编语言清清楚楚的写出了
每一个表达式的计算顺序。通过这种方式,
你就可以清楚的了解,你所使用的编译器,
到底是如何处理加加,或者减减运算的了。
当然,我绝对不鼓励所有的同学都去这么做。只是对
那些有兴趣又有一定基础的同学,你可以采取这个办法。
ok,关于算术运算符,我们就讲这么多。