作者RishYang (Rish)
看板C_and_CPP
标题Re: [问题] 什麽情况下会从後往前做运算?
时间Sat May 11 13:03:24 2019
前两楼有提到这个问题与第八诫相关
不过第八诫可能有些不够清楚
https://reurl.cc/0nZmk
https://reurl.cc/YQ0D4
这两篇看完就可以解开你心中的疑惑
时间有限,让我为你简单整理一下部分内容
先从简单的四则运算开始
int ans = 1+2+3+4;
ans是10
原因是加法的结合方向(associativity)
加法的结合方向是向左,可得到:
(((1+2)+3)+4)
*下方有结合方向的补充
再来复杂一点的
int ans = 1*2+6/3;
ans是4
因为((1*2)+(6/3))而不是(1*(2+6)/3)
是由於乘法(*)运算子优先权(precedence)较加法(+)高
国小四则运算口号:
先乘除,後加减,括号要先算
根据口号,但是要先算(1*2)还是(6/3)?
两个括号的结果互相'独立',其中一个先算不影响答案
1 * 2 = 2不影响後面的(6/3),这就是我指的独立
回到你问的两个例子
c = sub1(a,&b)+sub2(&a,b);
是加号左边先还是右边先算(先求值)
'先算'涉及求值顺序(Order of evaluation)
求值顺序没有'左到右'或'右到左'的顺序
printf("%d\n%d\n%d\n%d\n",a+b+c+d,(b*=a),(a+=d),(d++));
a+b+c+d, (b*=a), (a+=d), (d++)
以上四个求值地位相同,不会有哪个求值一定会先做
由於一个向左,一个向右,加上国小口号
让你误会存在'执行顺序方向',实际上执行顺序是假议题
没有一个执行顺序方向,各自表述的空间
是因为你的求值并非'独立',所以你才被电脑(可能是编译或是执行时期)误导
希望你看完,更能体会第八诫字句的含意(以下为第八诫节录)
当一段程式码中,某个变数的值用某种方式被改变一次以上,
例如++x/--x/x++/x--/function(&x)(能改变x的函式)
- 如果Standard没有特别去定义某段叙述中哪个部份必须被先执行,
那结果会是undefined behavior(结果未知)。
- 如果Standard有特别去定义执行顺序,那结果就根据执行顺序决定。
个人臆测:
不定义执行顺序是为了保持与数学运算逻辑的相容性
让C语言优雅又好入门的方法
其实把叙述一行行写出来,并不会逊於用一行完成
追求程式逻辑清晰比短小可能来的重要
*结合方向
http://codepad.org/hR8UFMOb
我想这个例子应该可以说明,乘除法向左结合的特性
结合方向遇上非独立的求值还是会有问题的
最後送给原Po: '凡物皆数'----毕达哥拉斯
C语言里大家都是传值,不要分这麽细
很少发文,请鞭小力一点
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 36.237.199.112
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1557551006.A.060.html
1F:推 Schottky: 推 05/11 13:55
2F:推 ohmylove347: 推 05/11 15:45
3F:→ RishYang: 编译器可以检查Wsequence-point 05/11 16:35
4F:→ RishYang: 编译-Wall起来,八诫不会难 05/11 16:38
5F:推 cuttheshit: 感谢大大耐心解惑 虽然还是不太懂 决定先跳过这个点了 05/11 16:51
6F:→ cuttheshit: "以上四个求值地位相同,不会有哪个求值一定会先做" 05/11 16:53
7F:→ cuttheshit: 编译结果那四个参数的取值顺序是 4,3,2,1 05/11 16:54
8F:→ cuttheshit: 那为何不能是 4,2,3,1呢 不禁有这样子的疑惑 05/11 16:54
9F:→ cuttheshit: 因为第一条式子也是"後面的结果先做有可能改动到前面" 05/11 16:56
10F:→ cuttheshit: 的情况 可是却可以是从左边开始算 05/11 16:56
11F:推 cuttheshit: 若是第二条用"因为後面先做会影响到前面的结果,所以先 05/11 17:00
12F:→ cuttheshit: 做後面" 那麽又跟第一条式子矛盾了 主要是卡在这里 05/11 17:01
13F:推 cuttheshit: 原本做题目好好的,自从遇到case2那条奇怪的式子後 05/11 17:06
14F:→ cuttheshit: 反而导致往後做时,一直会冒出一个念头 是不是该後往前 05/11 17:07
15F:→ cuttheshit: 有种一知半解最危险的感觉,反而会顾虑太多 05/11 17:09
16F:推 art1: 「不要在一个运算式中,写出变数会互相影响的程式码」 05/11 17:20
17F:→ RishYang: 在这个问题上不用担心会有一知半解的情形 05/11 18:11
18F:→ RishYang: art1所言是整篇重点,没有这种疑义才是良好的程式码 05/11 18:18