短路评估和副作用[重复]

Posted

技术标签:

【中文标题】短路评估和副作用[重复]【英文标题】:Short circuit evaluation and side effects [duplicate] 【发布时间】:2011-04-07 20:03:10 【问题描述】:

好吧,我有点不好意思问这个问题,但我只是想确定一下……

众所周知,C 在布尔表达式中使用短路求值:

int c = 0;
if (c && func(c))  /* whatever... */ 

在该示例中,func(c) 未被调用,因为 c 的计算结果为 0。但是,如果比较的副作用会改变接下来要比较的变量,那么更复杂的例子呢?像这样:

int c; /* this is not even initialized... */
if (canInitWithSomeValue(&c) && c == SOMETHING)  /*...*/ 

函数canInitWithSomeValue 返回真并在成功的情况下改变给定指针的值。是否保证后续比较(本例中为c == SOMETHING)使用canInitWithSomeValue(&c) 设置的值?

不管编译器使用了多么重的优化?

【问题讨论】:

我认为您可能会混淆短路评估和编译器优化。在第一个示例中,编译器将优化掉整个 if 语句,因为它永远无法运行。短路评估意味着如果您有 if(func1() && func2()) ... ,并且 func1() 在运行时 评估为假(即在编译时不明确),那么代码不应检查 func2() - 编译器应该精心设计机器代码,如果func1() 为假,则不会调用func2() int c = 0 在比较时表明c 等于0,我意识到在这种简单的情况下编译器会优化整个if 啊,我很抱歉。我误读了你。我很抱歉。 【参考方案1】:

是否保证后续比较(本例中为 c == SOMETHING)使用由 canInitWithSomeValue(&c) 设置的值?

是的。因为有一个sequence point

&&(逻辑与)、||(逻辑或)和逗号运算符的左右操作数的求值之间。例如,在表达式 *p++ != 0 && *q++ != 0 中,子表达式 *p++ != 0 的所有副作用都在尝试访问 q 之前完成。


序列点定义了计算机程序执行中的任何点,在该点可以保证先前评估的所有副作用都已执行,并且后续评估的副作用尚未执行。

【讨论】:

【参考方案2】:

是的。因为&&|| 运算符也称为序列点。后者定义了前一个操作的副作用何时应该完成,而下一个操作的副作用不应该开始。

【讨论】:

【参考方案3】:

if 语句复合条件内的求值严格从左到右。唯一会优化 if 中的第二个测试的情况是编译器是否可以 100% 确定第一个测试完全等于 false。

【讨论】:

以上是关于短路评估和副作用[重复]的主要内容,如果未能解决你的问题,请参考以下文章

当运算符优先级说不应该时,为啥短路评估会起作用?

关于短路评估的安全问题[重复]

C++如何处理&&? (短路评估)[重复]

UAEE China学术论文专栏丨王增平,等:基于k最短路径算法的负荷停电风险在线评估

记住C中运算符的评估顺序和优先级的快捷方式[重复]

布尔运算符的Python优先规则[重复]