在c语言中逻辑运算符的优先级是,C语言中逻辑运算符的优先级

本问题已经有最佳答案,请猛点这里访问。

#include

int main(void) {

int a = 0, b = 0, c = 0;

++a || ++b && ++c;

printf("%d %d %d", a, b, c);

return 0;

}

gcc 8.1.0的输出为1,0,0。 &&的优先级应高于||。

为什么b和c仍然是0?

由于短路。

表达式++a || ++b && ++c分组为++a || (++b && ++c)。但是,仅当++a是0时才评估||的右侧,但不是。

括号中的表达式不是应该在" ||"之前计算吗?

@EricShi绝对不是。 首先评估||的左侧。

@EricShi您将优先顺序与评估顺序混淆了...

@EugeneSh。 当场,非常重要。

@EricShi,应在||之前求值,但++a不是||,它是该操作数。

这里有三个问题:

优先顺序。

评估顺序。

逻辑运算符短路。

优先顺序意味着++a || ++b && ++c被评估为++a || (++b && ++c)。

但是,由于逻辑运算符的短路要求,因此首先评估++a。只有将其评估为false时,才会评估(++b && ++c)。在您的情况下,++a评估为true。因此,永远不会评估(++b && ++c)。

逻辑或运算符||(以及逻辑与运算符&&)是执行短循环操作的少数运算符之一。

C标准的6.5.14节对逻辑OR运算符进行了以下说明:

4 Unlike the bitwise | operator, the || operator guarantees

left-to-right evaluation; if the second operand is evaluated, there is

a sequence point between the evaluations of the first and second

operands. If the first operand compares unequal to 0, the second

operand is not evaluated.

因为++a的值为1,所以保证||运算符的结果为1,并且不对右侧进行求值。另外,由于&&的优先级高于||,所以||运算符的右侧为++b && ++c,这意味着不会评估++b或++c。

优先级仅控制表达式的解析方式,而不控制表达式的计算方式。算术*的优先级高于+,因此a * b + c被解析为(a * b) + c。但是,可以按任何顺序评估a,b和c中的每一个。必须先知道a * b的结果,然后才能将其添加到c的结果中,但这并不意味着a * b必须在c之前进行求值。

其次,与C中的大多数运算符不同,||和&&运算符强制执行从左到右的求值。像a || b && c这样的表达式将被解析为a || (b && c),但是a始终会首先被求值,并且b && c仅在a的结果为0时才被求值。

就优先级而言,x || y && z的作用与x + y * z相同:第二个运算符的绑定比第一个更紧密,并且这些表达式分别等效于x || (y && z)和x + (y * z)。

问题中的b和c不增加的原因是,除优先级外,逻辑运算还短路:一旦您足够了解结果,其余表达式将被跳过。 ||和&&都从左到右评估其参数,因此在a() || b()和a() && b()中,对a()的调用发生在对b()的调用之前。

在简单的情况下,如果a()返回true,则在表达式a() || b()中将不会执行对b()的调用,因为它不会影响结果。同样,如果a()返回false,则在表达式a() && b()中,将不执行对b()的调用。

在示例代码中,将不执行对b和c的递增操作,因为++a会生成非零值,因此表达式的结果为true,而无需在之后进行任何运算++a。

运算符优先级与求值顺序无关。优先级是将不同类型的运算符及其操作数进行分组的优先级。

所以,表达

++a || ++b && ++c;

将被评估为

++a || (++b && ++c);

逻辑与和逻辑或运算符构成序列点,因此保证了从左到右对其操作数的特定求值顺序。

评估顺序:

Ordering

......

If a sequence point is present between the subexpressions E1 and E2,

then both value computation and side effects of E1 are

sequenced-before every value computation and side effect of E2

Rules

.....

2) There is a sequence point after evaluation of the first (left) operand and before evaluation of the second (right) operand of the following binary operators: && (logical AND), || (logical OR), and , (comma).

逻辑或运算(expr1 || expr2)采用短路行为。也就是说,如果expr1是逻辑1 (true),则不评估expr2。

a,b和c的初始值为0。在表达式中:

++a || ++b && ++c;

++a->预递增a。

也就是说,表达式++a的值是a的增量值,该值将是1。由于||运算符具有短路行为,因此不会评估||的右侧表达式。因此,您将获得输出-1 0 0。

为了更好地理解,只需尝试在表达式中更改++a-> a++。

后递增运算符还将操作数的值增加1,但表达式的值是该操作数在增量运算之前的原始值。因此,a++将被评估为0,并且由于短路行为,将评估||运算符(++b && ++c)的右侧表达式。

逻辑AND操作(expr1 && expr2)也采用短路行为。如果发生逻辑短路,则只有当第一个操作数expr1不能完全确定结果时,才对第二个操作数expr2求值。也就是说,仅当expr1是逻辑1 (true)并且++b会导致1时,才会评估expr2。所以,如果你这样做

a++ || ++b && ++c;

^^^

输出将是-1 1 1。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值