关于短路评估的安全问题[重复]
Posted
技术标签:
【中文标题】关于短路评估的安全问题[重复]【英文标题】:Safety concerns about short circuit evaluation [duplicate] 【发布时间】:2011-11-26 17:07:07 【问题描述】:可能重复:Is short-circuiting boolean operators mandated in C/C++? And evaluation order?
AFAIK 短路评估意味着布尔表达式仅被评估到我们可以保证其结果的程度。
这是 perl 中的一个常见习惯用法,我们可以在其中编写如下内容: (is_ok() 在“OK”时返回非零值)
is_ok() || die "It's not OK!!\n";
而不是
if ( ! is_ok() )
die "It's not OK!!\n";
这只是因为评估的顺序总是从左到右,这保证了最右边的语句只有在第一个语句不是“假”的情况下才会执行。
在 C 中我可以做类似的事情:
struct foo
int some_flag;
*ptr = 0;
/* do some work that may change value of ptr */
if ( 0!=ptr && ptr->some_flag )
/* do something */
使用这种成语安全吗?
或者在确保 ptr 不是零指针之前,编译器是否有可能生成评估 ptr->some_flag
的代码? (我假设如果它是非空的,它指向一些有效的内存区域)。
这种语法使用起来很方便,因为它可以在不丢失可读性的情况下节省打字(无论如何我认为)。但是我不确定它是否完全安全,这就是我想了解更多信息的原因。
注意:如果编译器对此有影响,我使用的是 gcc 4.x
【问题讨论】:
让我感到困惑的是,在 2011 年我们收到编译器警告时,人们仍然写完全不直观的if (0 == x)
而不是 if (x == 0)
。 if (0 != x)
很奇怪; if (0 != ptr)
更糟! if (ptr)
,确定吗?
我最近了解到我们现在称之为“尤达条件”***.com/questions/2349378/…
@undur_gongor:哈,我喜欢!
【参考方案1】:
在上面的示例中是安全的,但是任何维护此类代码的人都可能没有意识到存在对评估顺序的依赖并导致一个有趣的错误。
【讨论】:
【参考方案2】:/* do some work that may change value of ptr */ if ( 0!=ptr && ptr->some_flag ) /* do something */
使用这种成语安全吗?
是的。
【讨论】:
【参考方案3】:标准保证短路运算符(||
和&&
)的评估顺序是从左到右(否则它们将失去部分用处)。
§6.5.13 ¶4
与按位二进制
&
运算符不同,&&
运算符保证从左到右的评估; 在计算第一个操作数之后有一个序列点。如果第一个操作数 比较等于0
,不计算第二个操作数。
§6.5.14 ¶4
与按位
|
运算符不同,||
运算符保证从左到右的评估;有 评估第一个操作数之后的序列点。如果第一个操作数比较 不等于 0,不计算第二个操作数。
【讨论】:
【参考方案4】:或者编译器是否有可能生成代码 在确保 ptr 不为零之前评估 ptr->some_flag 指针?
不,零机会。标准保证ptr->some_flag
在第一个操作数为假时不会被计算。
6.5.13-4
与按位二进制 & 运算符不同,&& 运算符保证 从左到右的评价;之后有一个序列点 评估第一个操作数。 如果第一个操作数比较等于 0,不计算第二个操作数。
【讨论】:
以上是关于关于短路评估的安全问题[重复]的主要内容,如果未能解决你的问题,请参考以下文章