如果我有这样的情况:
if (X && Y) {}
编译器会检查Y
是否X
为假吗?它依赖于编译器吗?
C 规范(6.5.13)为您阐明了这一点:
4 与按位二进制 & 运算符不同,&& 运算符保证从左到右的求值;如果计算第二个操作数,则在第一个和第二个操作数的计算之间存在一个序列点。如果第一个操作数比较等于 0,则不计算第二个操作数。
所以 C 语言本身定义了 if X == 0
thenY
不会被检查。
Y
仅当是时才X
检查true
如果X
为假则Y
不会被检查
顺便说一句,检查是在执行运行时完成的,而不是在编译阶段
&&
和||
强制从左到右评估。如果计算第二个操作数,两者都将在第一个和第二个操作数之间引入一个序列点。如果表达式的结果可以单独从第一个操作数确定,则两者都不会计算第二个操作数。IOW, for X && Y
,Y
如果X
为假则不会被评估,而 for X || Y
,Y
如果X
为真则不会被评估。
请注意,优先级不影响评估顺序;给定一个表达式,例如X || Y && Z
,之前Y && Z
不会被计算X
,即使&&
它的优先级高于||
. X
首先被评估;如果结果为 0(假),则Y
进行评估。如果该结果为非零(真),则Z
进行评估。
这是在语言标准(2011 版,在线草案)的第 6.5.13 和 6.5.14 节中定义的,因此它不依赖于编译器。
如果Y
有副作用,或者如果访问它可能是未定义的行为(例如错误的指针取消引用),那么编译器必须确保Y
除非X
评估为真,否则不会评估它。但是,如果两者都X
没有Y
副作用并且编译器知道对它们的访问是明确定义的,它可能会选择以两种访问都发生的方式进行优化。