问题描述
int a=1,b=3,c=1;
if((a||c--)&&(c&&b--)) printf("%d",b);
printf("%d %d %d",a,b,c);
为什么代码打印“21 2 1”而不是“1 2 0”?
感谢您的帮助。
解决方法
因为 or 在 (a||c--) 中立即被评估为真,所以 c-- 永远不会被评估。编译器就是这样做的。如果一个陈述立即正确,它就不会费心评估其余的陈述。因此,c 永远不会递减作为 or 的右侧,永远不会被评估。
,你可以想象这个 if 语句
if((a||c--)&&(c&&b--)) printf("%d",b);
以下方式
if ( a )
{
if ( c )
{
if ( b-- )
{
printf("%d",b);
}
}
}
else if ( c-- )
{
if ( c )
{
if ( b-- )
{
printf("%d",b);
}
}
}
所以如果第一个 if 语句中的表达式
if ( a )
计算逻辑真然后这个 if 语句
else if ( c-- )
永远无法控制。
来自 C 标准(6.5.14 逻辑 OR 运算符)
4 与按位不同 |运算符 ||运营商保证 从左到右评估;如果计算第二个操作数,则有 第一个和第二个评估之间的序列点 操作数。 如果第一个操作数比较不等于 0,则第二个操作数 不计算操作数。
,||
和 &&
都强制从左到右评估 - 首先评估 LHS 并应用所有副作用,然后根据结果评估 RHS .
两个运算符都短路:
- 对于
a || b
,如果a
非零,那么无论1
的值如何,表达式的结果都是b
,所以b
未评估; - 对于
a && b
,如果a
为零,那么无论0
的值如何,表达式的结果都是b
,所以b
不是评估。
&&
的优先级高于 ||
,因此 a || b && c
被解析为 a || (b && c)
。
将所有这些放在一起,(a||c--)&&(c&&b--)
的计算方式如下:
-
a || c--
的计算方式如下:-
a
被求值 - 结果是1
,所以 -
c--
没有被评估;因为这个c
的值没有改变,并且 - 表达式的结果是
1
-
-
c && b--
的计算方式如下:-
c
被评估 - 它的结果是1
,所以 -
b--
被评估 - 结果是3
;作为副作用b
递减,并且 - 表达式的结果是
1
-
-
a || c--
和c && b--
的计算结果均为1
a
和 c
的值不变(分别为 1
和 1
),而 b
已递减,其值现在为 { {1}}。