关于短路评估的安全问题

可能重复:
是否在C / C ++中强制要求短路布尔运算符? 和评估顺序?

AFAIK短路评估意味着仅在我们可以保证其结果的点上评估布尔表达式。

这是perl中常见的习惯用法,我们可以编写如下内容:(is_ok()在“OK”上返回非零值)

is_ok() || die "It's not OK!!\n"; 

代替

 if ( ! is_ok() ) { die "It's not OK!!\n"; } 

这只能起作用,因为评估的顺序始终是从左到右,并且只保证最右边的语句只在第一个语句不是“false”时执行。

在CI中可以做类似的事情:

 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代码? (我假设如果它是非null,则指向一些有效的内存区域)。

这种语法使用起来很方便,因为它可以节省输入而不会失去可读性(我认为无论如何)。 但是我不确定它是否完全安全,这就是为什么我想了解更多。

注意:如果编译器对此有影响,我使用的是gcc 4.x.

短程运算符( ||&& )的评估顺序由标准保证从左到右(否则它们将失去部分有用性)。

§6.5.13¶4

与按位二元&运算符不同, &&运算符保证从左到右的评估; 在评估第一个操作数后有一个序列点。 如果第一个操作数比较等于0 ,则不计算第二个操作数。

§6.5.14¶4

与按位|不同 运算符, || 运营商保证从左到右的评估; 在评估第一个操作数后有一个序列点。 如果第一个操作数比较不等于0,则不计算第二个操作数。

或者,在确保ptr不是零指针之前,编译器是否有可能生成评估ptr-> some_flag的代码?

不,零机会。 标准保证,如果第一个操作数为假,则不会评估ptr->some_flag

6.5.13-4

与按位二元和运算符不同,&&运算符保证从左到右的评估; 在评估第一个操作数后有一个序列点。 如果第一个操作数比较等于0,则不计算第二个操作数

 /* do some work that may change value of ptr */ if ( 0!=ptr && ptr->some_flag ) { /* do something */ } 

使用这种成语是否安全?

是。

在上面的示例中它是安全的,但是任何维护此类代码的人都可能没有意识到存在对评估顺序的依赖并导致有趣的错误。