免费注册 查看新帖 |

Chinaunix

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

[C] [C实现]条件表达式的执行顺序是固定的吗? [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-09-28 16:46 |只看该作者 |倒序浏览
函数声明:
uint32_t fun(uint32_t *argv);

下面的代码检查函数参数(位于函数定义中):

if ((NULL == argv) || (3 < argv[1])) return -EINVAL;

我记得好像什么地方说过,这样的条件判断里
如果(NULL == argv)成立则不进行(3 < argv[1])的判断
执行顺序是从左到右

如果不保证这个顺序的话,那我必须写成下面这样:

if (NULL == argv) return -EINVAL;
if (3 < argv[1]) return -EINVAL;

最近被单片机的BUG搞得疑神疑鬼,C程序开始用类似汇编的风格来写了

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
2 [报告]
发表于 2012-09-28 16:52 |只看该作者
条件表达式? if (...) ... ? 这货是语句。而且它不管(...)内的求值顺序的。

顺序是因为logic or(||)的关系。必须是先||的左操作数NULL == argv然后是右操作数3 < argv[1]。
这顺序C语言是保证了的。
如果产生的代码先计算3 < argv[1],那就可以给那个编译器报bug了。


而如果是其他的,例如 if ( X & Y ), X 与 Y 的顺序就没保证了。

论坛徽章:
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 [报告]
发表于 2012-09-28 17:12 |只看该作者
OwnWaterloo 发表于 2012-09-28 16:52
条件表达式? if (...) ... ? 这货是语句。而且它不管(...)内的求值顺序的。

顺序是因为logic or(||)的 ...


你确信说的是 & 而不是 && 吧

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
4 [报告]
发表于 2012-09-28 17:19 |只看该作者
hellioncu 发表于 2012-09-28 17:12
你确信说的是 & 而不是 && 吧


说真的我希望C语言用 & 而不是 && 表达逻辑乘
估计当初先有&取地址,后面只好用 && 来表达逻辑乘了

论坛徽章:
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
5 [报告]
发表于 2012-09-28 17:23 |只看该作者
safedead 发表于 2012-09-28 17:19
说真的我希望C语言用 & 而不是 && 表达逻辑乘
估计当初先有&取地址,后面只好用 && 来表达逻辑乘了



应该是跟位操作 & 冲突吧

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
6 [报告]
发表于 2012-09-28 17:32 |只看该作者
回复 3# hellioncu

L && R 会保证先L后R
L & R 不知道谁现谁后。

没说错吧?

论坛徽章:
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
7 [报告]
发表于 2012-09-28 20:50 |只看该作者
OwnWaterloo 发表于 2012-09-28 17:32
回复 3# hellioncu

L && R 会保证先L后R


嗯,我也这么认为。
看你那段话,容易误解只有||是那样,而&&不是

论坛徽章:
0
8 [报告]
发表于 2012-09-28 20:59 |只看该作者

楼上几位的解释都是对的。

不过在实践中,比较推荐的做法是不要在 if (expr_a || expr_b) 的时候做什么实质性的‘写’操作。因为那样的代码读起来太累,容易隐藏bug。

比如楼主遇到的疑惑和担心,其实是完全可以避免的。之所以会有这麻烦,就是当初写代码的人水平太次,或者太爱卖弄。

建议楼主在有机会的时候,把那块代码改写一下,写成任何人都不会担心的代码,写成不会有任何迷惑的代码。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
9 [报告]
发表于 2012-09-28 21:39 |只看该作者
回复 7# hellioncu

原来是这个意思。。。
放心,木有手误。。。

表达式的操作数们有求值顺序的就这几个:
first , then
first && when_non_zero
first || when_zero
first ? when_non_zero: when_zero

凭记忆写的。
为了避免误导,又去翻了翻附录,也确实只有这几个。。。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
10 [报告]
发表于 2012-09-28 21:39 |只看该作者
回复 8# wwwsq


    ……………………我经常这么干……………………

通常是&&里面判断很多条件,然后顺手把实际操作当做最后一个条件,然后在if里面写错误处理:

  1. if (!cond1 || !cond2 || !cond3 || !do_something(v1, v2, v3))
  2.    printf("ERROR!");
复制代码
反正就是这么个意思吧。

还有就是while循环里面,给个实际的例子吧:
  1. static int read_one_char(ParseState *ps) {
  2.     if (isnewline(ps) || iseoz(ps))
  3.         return 0;
  4.     if (test_current(ps, ESCAPE_CHAR))
  5.         read_escape(ps);
  6.     else if (test_current(ps, COMMENT_CHAR))
  7.         skip_comment(ps);
  8.     else
  9.         save_and_next(ps);
  10.     return 1;
  11. }

  12. static size_t read_word(ParseState *ps) {
  13.     assert(!isspace(ps) || mb_bufflen(&ps->buff) > 0);
  14.     while (!isspace(ps) && read_one_char(ps))
  15.         ;
  16.     skip_whitespace(ps);
  17.     return mb_bufflen(&ps->buff);
  18. }
复制代码
这是从我写的ninja语言格式分析器里面随意抽出来的一段。read_one_char读取一个字节,然后进行实际操作,最后返回到底读到没(newline要特殊处理)。在这个情况下,while里面就直接&&搞事了,最后循环体是个空语句,因为事情都搞完了…………
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP