C和C ++操作数解析顺序
很多时候,我看到(有时写)代码与此示例类似:
int a=0, b=2; if( a && (b=func())!=0 ) { //...
问题是:标准是否保证这些陈述?
-
b
将不被触及(并保持值2
) - 不会调用
func()
反之亦然,如果我们写if( func()!=0 && a )
– 是否会调用标准保证func()
?
我对定义这个合法的特定标准段感兴趣。
UPD:我的拼写错误,从int a=1
更改为int a=0
确切的问题;
问题是:标准保证这些陈述吗?
更新的问题; 给定a=0
。 如果a==0
,则是,短路评估将启动并且不会调用func()
; 第二个操作数不会被评估。
如果a=1
(原来是),则相反; 将调用func()
– a
为1
因此为“true”,因此第二个操作数被计算(它是逻辑AND), b
将改变。 如果操作员已经||
(逻辑或),然后短路评估将启动并且不会调用func()
。
反之亦然,如果我们写
if( func()!=0 && a )
– 是否会调用标准保证func()
?
是的,始终会评估第一个操作数。
是的,C ++保证短路评估;
§5.14逻辑AND运算符
1
&&
运算符从左到右分组。 操作数都在上下文中转换为bool(第4条)。 如果两个操作数都为真,则结果为true,否则为false。 与&
不同,&&
保证从左到右的评估:如果第一个操作数为假,则不评估第二个操作数。2结果是一个布尔。 如果评估第二表达式,则在与第二表达式相关联的每个值计算和副作用之前,对与第一表达式相关联的每个值计算和副作用进行排序。
§5.15逻辑OR运算符
1
||
操作员组从左到右。 操作数都在上下文中转换为bool(第4条)。 如果其任一操作数为true,则返回true,否则返回false。 与|
不同 ,||
保证从左到右的评估; 此外,如果第一个操作数的计算结果为true,则不计算第二个操作数。2结果是一个布尔。 如果评估第二表达式,则在与第二表达式相关联的每个值计算和副作用之前,对与第一表达式相关联的每个值计算和副作用进行排序。
C的相应引号是;
§6.5.13逻辑AND运算符
4与按位二进制
&
运算符不同,&&
运算符保证从左到右的评估; 如果评估第二个操作数,则在第一个和第二个操作数的评估之间存在一个序列点。 如果第一个操作数比较等于0,则不计算第二个操作数。
§6.5.14逻辑OR运算符
4与按位
|
不同 运算符,||
运营商保证从左到右的评估; 如果评估第二个操作数,则在第一个和第二个操作数的评估之间存在一个序列点。 如果第一个操作数比较不等于0,则不计算第二个操作数。
从C-90标准。
6.5.13逻辑AND运算符
….
4与按位二进制和运算符不同,&&运算符保证从左到右的评估; 在评估第一个操作数后有一个序列点。 如果第一个操作数比较等于0,则不计算第二个操作数。
类似地,对于逻辑OR运算符。
&&
运算符要求两个操作数都为true。 如果第一个操作数的计算结果为false,则不会计算第二个操作数。 但是因为a
是1,它被认为是真的,并且第二个表达式(操作数)被评估。 因此func()
并将其结果分配给b
然后b
被测试为非零。
该标准保证了&&
序列中的语句从左到右进行评估,并且只要其中一个语句的计算结果为false,就不会对其右侧的语句进行评估。
问题是:标准保证这些陈述吗?
b将不被触及(并保持值2)
不会调用func()
不,实际上他们两个都错了。 因为它是operator &&
所以在这种特殊情况下不能应用快捷逻辑。
如果您将其更改为||
那么你的陈述是正确的 – 只有那时第一个操作数的评估(在这种情况下a = 1
)才足够,其余的被忽略。
当问题变为a = 0
然后是,两个语句都是正确且有保证的。