免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: donotblock

[C] 优先级,结合性,序列点, 你理解清楚了么? [复制链接]

论坛徽章:
0
发表于 2010-12-29 19:44 |显示全部楼层
受教了,以前在学校的时候,老师还真是没讲过“序列点”啊,什么的。

关于C的好多知识都还是在CU上学到的。

论坛徽章:
0
发表于 2010-12-29 19:58 |显示全部楼层
回复  davelv

  谢谢!
KBTiller 发表于 2010-12-29 19:41

看完第一部分我会写个详细的评论和讨论列表的,虽然现在还没看几章,但已经受益良多了。

论坛徽章:
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
发表于 2010-12-29 20:25 |显示全部楼层
回复 6# donotblock


    in any order  conforming to the precedence rules

    这个的意思是“以任何遵守优先级规则的顺序”吧,同样的条目在ISO/IEC 9899:1999(E)(应该就是C99)里面是这样的:

The order in which subexpressions are evaluated and the order in which side effects
takeplace, except as specified for the function-call (), &&, ||, ?:,and comma
operators (6.5).


    即子表达式的计算顺序是未指定的。但由于优先级和结合性的规则,为了计算某个子表达式可能需要计算另一个表达式,比如a*b+c,为了计算(a*b)+c,必须先计算a*b,优先级规则限制了这一点。

    另外,我认为表达式求值和side effects的发生并不一定同时。标准中只保证某序列点之前的side effects在序列点处已经发生,但子表达式求值总归是有一定顺序的,可能某个表达式被求值了,但side effects并未发生。

论坛徽章:
0
发表于 2010-12-29 21:22 |显示全部楼层
本帖最后由 donotblock 于 2010-12-29 21:23 编辑
回复  donotblock


    in any order  conforming to the precedence rules

    这个的意思是“以任 ...
zhaohongjian000 发表于 2010-12-29 20:25



    这个我觉得应该这样理解:
    优先级与结和性的作用只是说a*b+c应该这样分组(a*b)+c, 而不是a * (b +c).  你说的那个隐式的计算顺序应该是操作符+的语义决定的,(a*b)是+的第一个操作数。而evaluation,我觉得翻译成求值还没有完全体现原词的意味,并不只是计算出一个值的意思,  本身就包括side effect。

An operator specifies an operation to be performed (an evaluation )
that yields a value, or yields a designator, or produces a side
effect, or a combination thereof.


其实我们的观点没有大的不同,这样辨析下去有点学究的意味了

论坛徽章:
0
发表于 2010-12-30 08:43 |显示全部楼层
本帖最后由 davelv 于 2010-12-30 08:44 编辑
回复  donotblock


    in any order  conforming to the precedence rules

    这个的意思是“以任 ...
zhaohongjian000 发表于 2010-12-29 20:25

求值无顺序,这点C标准已经说的很明确了。
例如a*b+c这个表达式,不一定先计算a*b,也许先计算c,c的值无非就是c变量本身。这点也许不够明确,但是举个不恰当的例子。
++a*b + a 如果真的有计算顺序,这个表达式也不会是未定义的行为了。

论坛徽章:
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
发表于 2010-12-30 09:15 |显示全部楼层
回复 14# donotblock


    优先级与结和性的作用只是说a*b+c应该这样分组(a*b)+c, 而不是a * (b +c).  你说的那个隐式的计算顺序应该是操作符+的语义决定的,(a*b)是+的第一个操作数。而evaluation,我觉得翻译成求值还没有完全体现原词的意味,并不只是计算出一个值的意思,  本身就包括side effect。


    这样解释好像的确没什么问题,关于这一点应该是观察角度不一样。不过关于求值,我不同意你的观点。如果一个表达式求值的时候其side effect就发生了,一切就简单多了。side effects的发生时间只由序列点来保证,比如:
  1. int a = 2;
  2. int b = a++ + a++;
复制代码
两个a++的计算顺序是不确定的,但如果side effects在求值的时候就发生了,那么无论先求哪个结果都是5,而实际情况不是这样(gcc下不开优化结果是4)。而如果认为求值的时候side effects不一定发生就能很好的解释了:尽管某个a++求值了,但side effects可能并未发生,a的值并未改变,于是结果为4。
    至于那段引文,只是指明了那些“动作”被执行,并未说合适执行,否则也用不着序列点了。

论坛徽章:
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
发表于 2010-12-30 09:20 |显示全部楼层
求值无顺序,这点C标准已经说的很明确了。
例如a*b+c这个表达式,不一定先计算a*b,也许先计算c,c的值无 ...
davelv 发表于 2010-12-30 08:43



    我想说的不是a*b 和 c的值那个先计算,而是为了计算a*b + c的值,必须先计算a*b,这个逻辑上的顺序不可能有例外的。

论坛徽章:
0
发表于 2010-12-30 09:30 |显示全部楼层
回复 17# zhaohongjian000
实现中的无序性是给编译器优化留的空间,而不是给人类用的。
但是很明显产生了一个副作用就是序列点问题,只要我们保证了序列点内的一致性,在逻辑上按照有运算顺序的规则来做是没有问题的。

这样的话,咱们的想法是不是就一致了。

论坛徽章:
0
发表于 2010-12-30 09:38 |显示全部楼层
回复 16# zhaohongjian000

并不是说side effect一定同时发生,而是说evaluation这个词本身就包含触发side effect这个意思,但什么时候触发未定。 不像中文“求值”这个词,就是求出结果的意思。 还是无歧义

论坛徽章:
0
发表于 2010-12-30 09:43 |显示全部楼层
本帖最后由 donotblock 于 2010-12-30 10:10 编辑
我想说的不是a*b 和 c的值那个先计算,而是为了计算a*b + c的值,必须先计算a*b,这个逻辑上的顺 ...
zhaohongjian000 发表于 2010-12-30 09:20

回复  zhaohongjian000
实现中的无序性是给编译器优化留的空间,而不是给人类用的。
但是很明显产生了一 ...
davelv 发表于 2010-12-30 09:30



    这一点可以这样举个例子:
    对于表达式
  1. a=b++
复制代码
编译器可以这样来实现:(伪码)
  1. a = b
  2. b=b+1
复制代码
也可以这样:(伪码)
  1. b=b+1
  2. a=b-1
复制代码
都是符合标准的,a=b++只能保证把b未加1之前的值赋给a,而且b要加上1


至于a*b + c必须先算a*b这个还是操作符的要求,标准的注27详细解释了这个问题,就是说优先级高的操作符组成的表达式(或者括号括起来的)是允许作为优先级低的操作符的操作数。

就是说这句话的语义是表达式a*b的值要加上表达式c的值,对于+来说,先算a*b还是先算c还是未定义。 而如果a*b或c有副作用,什么时候发生也是未定义的
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

DTCC2020中国数据库技术大会

【架构革新 高效可控】2020年12月21日-23日第十一届中国数据库技术大会将在北京隆重召开。

大会设置2大主会场,20+技术专场,将邀请超百位行业专家,重点围绕数据架构、AI与大数据、传统企业数据库实践和国产开源数据库等内容展开分享和探讨,为广大数据领域从业人士提供一场年度盛会和交流平台。

http://dtcc.it168.com


大会官网>>
  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP