免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 4525 | 回复: 33
打印 上一主题 下一主题

[C] 优先级!=求值顺序 [复制链接]

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-05-04 16:17 |只看该作者 |倒序浏览
i+++++i这种月经帖子现在有朝周经日经发展的趋势,写个帖子发发牢骚。

优先级!=求值顺序

表达式a+b*c,都知道这个表达式的值等于a+(b*c)而不是(a+b)*c,为什么?因为乘号的优先级比加号高。这段是废话。

但谁告诉你一定要先算b和c再算a了?不能把a先算出来吗?不能把c先算出来吗?不能在这个过程中顺便去干点别的吗?如果abc都是无副作用的子表达式,会对结果有影响吗?这一段明明还是废话为什么就有很多人想不明白?

那如果abc中的某些是有副作用的表达式呢?那么不同的求值顺序就会造成不同的结果了对不?比如说子表达式a在屏幕上输出“SB”,子表达式b输出“是”,子表达式c输出“谁”,如果求值顺序是abc,输出的就是“SB是谁”,如果顺序是cba,输出的就是“谁是SB”,对不?

有的语言规定了子表达式的求值顺序,那么像i+++++i这种问题就有标准答案,但C/C++没有规定,只是告诉你编译器觉着怎么好就怎么来,那么上面的表达式到底输出什么?不确定对不?

所以C/C++标准规定,上述表达式输出的结果是:

谁这么写谁SB

论坛徽章:
36
CU大牛徽章
日期:2013-09-18 15:24:20NBA常规赛纪念章
日期:2015-05-04 22:32:03牛市纪念徽章
日期:2015-07-24 12:48:5515-16赛季CBA联赛之辽宁
日期:2016-03-30 09:26:4715-16赛季CBA联赛之北控
日期:2016-03-30 11:26:2315-16赛季CBA联赛之广夏
日期:2016-05-20 15:46:5715-16赛季CBA联赛之吉林
日期:2016-05-24 11:38:0615-16赛季CBA联赛之青岛
日期:2016-05-30 13:41:3215-16赛季CBA联赛之同曦
日期:2016-06-23 16:41:052015年亚洲杯之巴林
日期:2015-02-03 15:05:04CU大牛徽章
日期:2013-09-18 15:24:52CU十二周年纪念徽章
日期:2013-10-24 15:46:53
2 [报告]
发表于 2015-05-04 16:28 |只看该作者
太有才了,竟然不知道要说什么好.

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
3 [报告]
发表于 2015-05-04 16:30 |只看该作者
通俗易懂,这样再不明白的,那真是S13了

论坛徽章:
6
酉鸡
日期:2013-11-04 15:30:02巳蛇
日期:2014-01-23 10:36:23双鱼座
日期:2014-01-23 13:08:332015亚冠之鹿岛鹿角
日期:2015-09-03 14:36:002015亚冠之武里南联
日期:2015-09-18 10:48:1315-16赛季CBA联赛之山西
日期:2016-05-05 00:05:33
4 [报告]
发表于 2015-05-04 16:35 |只看该作者
总结到位,五星好评~

论坛徽章:
12
巳蛇
日期:2013-09-16 15:32:242015年辞旧岁徽章
日期:2015-03-03 16:54:152015年亚洲杯之约旦
日期:2015-02-11 14:38:37双鱼座
日期:2015-01-05 11:05:47戌狗
日期:2014-12-08 09:41:18戌狗
日期:2014-08-15 09:29:29双子座
日期:2014-08-05 09:17:17卯兔
日期:2014-06-08 15:32:18巳蛇
日期:2014-01-27 08:47:08白羊座
日期:2013-11-28 21:04:15巨蟹座
日期:2013-11-13 21:58:012015年亚洲杯之科威特
日期:2015-04-17 16:51:51
5 [报告]
发表于 2015-05-04 17:45 |只看该作者
本帖最后由 zhaohongjian000 于 2015-05-12 11:30 编辑

update:修正一些错误

既然楼主都发帖了,我就补充两句,因为实际情况还要更复杂。

优先级决定的是操作符和操作数如何结合,而“求值”,假定这个单词对应的英文是evaluation的话,则实际有两种“求值”:
1. 值的计算(value computation)
2. 副作用(side effect)

这种区分意味着一个有副作用的表达式(比如修改了一个变量的值),它的副作用和它的值的计算不一定是同时发生的。

在C++11中:
对于后置自增/自减,值的计算在副作用之前;
对于前置自增/自减,值的计算在副作用之后。

比如:
  1. i=i++;
复制代码
操作符“=”的值的计算依赖于后置++的运算结果,但两者的副作用何时发生并没有保证。所以行为是未定义的。

而:
  1. i=++i;
复制代码
由于有“对于前置自增/自减,值的计算在副作用之后”这条保证,所以是良好定义的。但这仅针对C++11,
C中似乎并没有关于自增自减操作符的这两条保证(有知道的同学可以补充下),C++11之前也是未定义的。

更麻烦的是C和C++的关于求值顺序、序列点的内容在新版本(C99、C11、C++11等)都有改动/补充,所以
实在是太麻烦了。

所以我的基本建议是:
1. 一些操作符的操作数的求值顺序是不确定的,这个是基础知识,要记住
2. 一些操作符的操作数的请求顺序是确定的,这个也要记住
3. 避免在一个表达式中修改一个变量超过一次
考虑到后面的例子,应该补充为:
在一个表达式中如果修改过某个变量,就不要在这个表达式中再次使用这个变量。

至于那些复杂的规则,没事的时候倒是可以看看,但作为写代码的参考就太不实用了。

参考资料:
http://en.cppreference.com/w/cpp/language/eval_order
http://en.cppreference.com/w/c/language/eval_order

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
6 [报告]
发表于 2015-05-04 17:57 |只看该作者
回复 5# zhaohongjian000

你说的这些我没写在帖子里,因为这么简单的事情都要年年讲月月讲,再加上sequencepoint/happen-before/after什么的估计好多人连我在吐槽什么都搞不清了。

论坛徽章:
12
巳蛇
日期:2013-09-16 15:32:242015年辞旧岁徽章
日期:2015-03-03 16:54:152015年亚洲杯之约旦
日期:2015-02-11 14:38:37双鱼座
日期:2015-01-05 11:05:47戌狗
日期:2014-12-08 09:41:18戌狗
日期:2014-08-15 09:29:29双子座
日期:2014-08-05 09:17:17卯兔
日期:2014-06-08 15:32:18巳蛇
日期:2014-01-27 08:47:08白羊座
日期:2013-11-28 21:04:15巨蟹座
日期:2013-11-13 21:58:012015年亚洲杯之科威特
日期:2015-04-17 16:51:51
7 [报告]
发表于 2015-05-04 18:06 |只看该作者
回复 6# windoze


    可不是嘛,那两页资料我都看晕了。我觉得这是C、C++对带副作用的运算符限制太少导致的。由于语法上合法又产生了奇怪的结果,
语言的使用者需要了解一些本来是语言的实现者才用的到的知识,才能理解这些结果产生的原因。

论坛徽章:
36
子鼠
日期:2013-08-28 22:23:29黄金圣斗士
日期:2015-12-01 11:37:51程序设计版块每日发帖之星
日期:2015-12-14 06:20:00CU十四周年纪念徽章
日期:2015-12-22 16:50:40IT运维版块每日发帖之星
日期:2016-01-25 06:20:0015-16赛季CBA联赛之深圳
日期:2016-01-27 10:31:172016猴年福章徽章
日期:2016-02-18 15:30:3415-16赛季CBA联赛之福建
日期:2016-04-07 11:25:2215-16赛季CBA联赛之青岛
日期:2016-04-29 18:02:5915-16赛季CBA联赛之北控
日期:2016-06-20 17:38:50技术图书徽章
日期:2016-07-19 13:54:03程序设计版块每日发帖之星
日期:2016-08-21 06:20:00
8 [报告]
发表于 2015-05-04 19:43 |只看该作者
好评                                                      

论坛徽章:
89
水瓶座
日期:2014-04-01 08:53:31天蝎座
日期:2014-04-01 08:53:53天秤座
日期:2014-04-01 08:54:02射手座
日期:2014-04-01 08:54:15子鼠
日期:2014-04-01 08:55:35辰龙
日期:2014-04-01 08:56:36未羊
日期:2014-04-01 08:56:27戌狗
日期:2014-04-01 08:56:13亥猪
日期:2014-04-01 08:56:02亥猪
日期:2014-04-08 08:38:58程序设计版块每日发帖之星
日期:2016-01-05 06:20:00程序设计版块每日发帖之星
日期:2016-01-07 06:20:00
9 [报告]
发表于 2015-05-04 22:24 |只看该作者
你们真是无聊,看见这么写直接骂他傻逼不就完了,浪费那个实践精力干啥。

论坛徽章:
35
双子座
日期:2014-05-09 17:56:38程序设计版块每日发帖之星
日期:2015-08-30 06:20:00程序设计版块每日发帖之星
日期:2015-12-24 06:20:0015-16赛季CBA联赛之上海
日期:2015-12-27 11:07:07程序设计版块每日发帖之星
日期:2016-01-12 06:20:0015-16赛季CBA联赛之北京
日期:2016-01-15 01:01:2115-16赛季CBA联赛之浙江
日期:2016-01-15 22:38:20程序设计版块每日发帖之星
日期:2016-01-18 06:20:00每日论坛发贴之星
日期:2016-01-18 06:20:0015-16赛季CBA联赛之北控
日期:2016-01-30 21:43:01程序设计版块每日发帖之星
日期:2016-02-08 06:20:0015-16赛季CBA联赛之山西
日期:2016-02-20 10:54:41
10 [报告]
发表于 2015-05-07 20:40 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP