我无法弄清楚如何在C中评估此表达式? 我对printf中的表达式的评估有点困惑? 如果printf中的表达式从右到左进行评估,那么表达式的评估应该在遇到(c> 10)之后停止,但它会在输出屏幕上打印“1”?
这不是C的确切语法,而是向我询问的一个问题。
integer a = 50, b = 25, c = 0;
printf( a > 45 || b > 50 && c > 10 );
答案 0 :(得分:2)
此表达式
a > 45 || b > 50 && c > 10
相当于表达式
( a > 45 ) || ( b > 50 && c > 10 )
因此,如果此子表达式( a > 45 )
的计算结果为true,则第二个子表达式将不会计算,结果等于1(类型为int)。
否则此子表达式
( b > 50 && c > 10 )
相当于
( b > 50 ) && ( c > 10 )
如果( b > 50 )
的计算结果为false,则整个结果为false(C中为0),第二个子表达式将不会计算。否则结果是值
子表达式c > 10
。如果是c > 10
,那么结果是int类型为1的对象,如果不是( c > 10 )
,则结果的值为0.
如果变量具有问题中显示的值
int a = 50, b = 25, c = 0;
然后是第一个子表达式
a > 45
计算结果为true,结果为int类型1。第二个子表达式
b > 50 && c > 10
甚至不会评估。
考虑以下示范程序
#include <stdio.h>
int f( int x )
{
printf( "f is called for %d\n", x );
return x;
}
int main( void )
{
int a = 50, b = 25, c = 0;
f( f( a ) > 45 || f( b ) > 50 && f( c ) > 10 );
return 0;
}
它的输出是
f is called for 50
f is called for 1
正如您所看到的,计算表达式f( a ) > 45
就足以使结果等于1
。
答案 1 :(得分:1)
这将是未定义的行为。 printf的第一个参数必须是格式字符串。最有可能它会崩溃。拯救你的是“整数”不是一个类型,所以它不会编译。
答案 2 :(得分:1)
||
和&&
运营商都强制进行从左到右的评估。在评估右侧操作数之前,将对左侧操作数进行全面评估(并应用所有副作用)。
此外,两个运算符短路 - 根据左侧操作数的值,可能根本不会评估右侧操作数。
有关
a || b
如果a
为真,那么无论b
的值如何,整个表达式都为真,因此不会评估b
。
同样,
a && b
如果a
为false,则无论b
的值是什么,整个表达式都为false,因此不会评估b
。
&&
的优先级高于||
,因此
a || b && c
将被解析为
a || (b && c)
和
a && b || c
将被解析为
(a && b) || c
因此...
a > 45 || b > 50 && c > 10
被解析为
a > 45 || (b > 50 && c > 10 )
自a == 50
以来,a > 45
为真。由于a > 45
是||
运算符的左侧操作数,因此无论右侧操作数如何,整个表达式都为true,因此根本不会计算b > 50 && c > 10
。
表达式的结果是1(真)。
不幸的是,printf
期望其第一个参数指向字符串(格式字符串),而1
很可能不是您平台上的有效地址,因此此代码的结果将是很可能是一个段错误。简单的解决方法是编写
printf( "%d\n", a > 45 || b > 50 && c > 10 );
答案 3 :(得分:0)
表达式出现的上下文会影响是否评估它,而不是如何。评估较大表达式的子表达式的顺序由operator precedence and associativity控制。
在您的表达式中的运算符中,>
具有最高优先级,然后是&&
,然后是||
。所有员工从左到右。因此,您的表达式的计算方式与它的编写方式完全相同:
(a > 45) || ((b > 50) && (c > 10))
此外,&&
和||
运算符执行短路评估。这对你来说似乎是一个混乱点。短路评估意味着如果&&
或||
操作的结果由左侧操作数的值确定,则该操作的右侧操作数 未评估。这不会影响是否或如何评估其他操作,除非将短路操作的结果用作操作数。
但是,在这种情况下,由于||
从左到右关联,因此首先评估a > 45
,生成1
(true)。因为这决定了||
操作的结果,所以不评估其右侧操作数。相对运算符优先级产生右侧操作数是整个表达式的其余部分,如上所示,因此不会对其进行评估。但是,即使 进行了评估,整个表达式的结果仍然是1
,因为左侧操作数的计算结果为1
,而不管右手子的表达。这就是为什么||
的右侧不需要评估的原因。