如果我有这样的情况:
if (X && Y) {}
如果X为false,编译器会检查Y吗?是否依赖于编译器?
X
Y
jaql4c8m1#
在C和most other languages中,保证短路评估。因此,Y仅在X计算为true时才被计算。这同样适用于X || Y-在这种情况下,Y仅在X计算为false时才被计算。请参阅Mike's answer,以获得对C规范的引用,其中提到并保证了此行为。
X || Y
zlwx9yxi2#
C规范(6.5.13)为您阐明了这一点:4与按位二元&运算符不同,&&运算符保证从左到右求值;如果第二操作数被求值,则在第一和第二操作数的求值之间存在序列点。如果第一个操作数比较等于0,则不计算第二个操作数。所以C语言本身定义了如果X == 0,那么Y将不会被检查。
X == 0
ego6inou3#
仅当X为true时,才检查Y如果X为false,则不会检查Y
true
BTW检查在执行运行时完成,而不是在编译阶段
lymnna714#
&&和||都强制从左到右求值。如果计算第二个操作数,则两者都将在第一个操作数和第二个操作数之间引入序列点。如果表达式的结果可以仅从第一个操作数确定,则两者都不会计算第二个操作数。IOW,对于X && Y,如果X为false,则不会评估Y,而对于X || Y,如果X为true,则不会评估Y。请注意,优先级并不影响求值顺序;给定像X || Y && Z这样的表达式,Y && Z将 * 不会 * 在X之前被求值,即使&&的优先级高于||。X首先被评估;如果结果为0(false),则计算Y。如果结果为非零(true),则计算Z。这在language standard(2011版,在线草稿)的第6.5.13和6.5.14节中定义,因此它不依赖于编译器。
&&
||
X && Y
X || Y && Z
Y && Z
Z
1tu0hz3e5#
如果Y有副作用,或者访问它可能是未定义的行为(例如,bad pointer dereference),则编译器必须确保不对Y求值,除非X求值为true。但是,如果X和Y都没有副作用,并且编译器知道对它们的访问是定义良好的,那么它可能会选择以这样一种方式进行优化,即两种访问都发生。
5条答案
按热度按时间jaql4c8m1#
在C和most other languages中,保证短路评估。因此,
Y
仅在X
计算为true时才被计算。这同样适用于
X || Y
-在这种情况下,Y
仅在X
计算为false时才被计算。请参阅Mike's answer,以获得对C规范的引用,其中提到并保证了此行为。
zlwx9yxi2#
C规范(6.5.13)为您阐明了这一点:
4与按位二元&运算符不同,&&运算符保证从左到右求值;如果第二操作数被求值,则在第一和第二操作数的求值之间存在序列点。如果第一个操作数比较等于0,则不计算第二个操作数。
所以C语言本身定义了如果
X == 0
,那么Y
将不会被检查。ego6inou3#
仅当
X
为true
时,才检查Y
如果
X
为false,则不会检查Y
BTW检查在执行运行时完成,而不是在编译阶段
lymnna714#
&&
和||
都强制从左到右求值。如果计算第二个操作数,则两者都将在第一个操作数和第二个操作数之间引入序列点。如果表达式的结果可以仅从第一个操作数确定,则两者都不会计算第二个操作数。IOW,对于X && Y
,如果X
为false,则不会评估Y
,而对于X || Y
,如果X
为true,则不会评估Y
。请注意,优先级并不影响求值顺序;给定像
X || Y && Z
这样的表达式,Y && Z
将 * 不会 * 在X
之前被求值,即使&&
的优先级高于||
。X
首先被评估;如果结果为0(false),则计算Y
。如果结果为非零(true),则计算Z
。这在language standard(2011版,在线草稿)的第6.5.13和6.5.14节中定义,因此它不依赖于编译器。
1tu0hz3e5#
如果
Y
有副作用,或者访问它可能是未定义的行为(例如,bad pointer dereference),则编译器必须确保不对Y
求值,除非X
求值为true。但是,如果X
和Y
都没有副作用,并且编译器知道对它们的访问是定义良好的,那么它可能会选择以这样一种方式进行优化,即两种访问都发生。