代码:
#include<stdio.h>
int main()
{
int j = 7, i = 4;
j = j || ++i && printf("you can");
printf("%d %d",i,j);
return 0;
}
输出: 4 1
[代码链接] [1]
&&
的优先级高于逻辑||
。&&
)中,如果第一个操作数计算结果为false而不是第二个将不进行评估,并且在逻辑OR中(||)
如果第一个操作数计算为true
,则第二个不会被评估。true
,因此j为1。疑惑:
为什么没有遵循第一条规则?不应该是正确的吗?
j=(j||((++i) &&printf("you can")));
因此,i
语句中printf
的值变为5。
为什么这里违反了一般优先规则?当两个运算符的优先级相同时,相关性开始起作用。编译器是否应该首先查看是评估||
还是&&
?
如果首先评估||
,这不应该是我所知的,那么结果是正确的。但是,如果没有先评估,那么你应该打印51.
答案 0 :(得分:4)
在这个表达式中:
j = j || ++i && printf("you can");
在||
之后有一个序列点,它从左到右进行评估。由于j不为零,因此不评估表达式的其余部分。因此,j || (....)
变为真,即1.因为++i
未被评估,所以我仍为4.因此,输出为4, 1
。
来自C标准:
附件C
- 以下运算符的第一个操作数的结束:逻辑AND &安培;&安培; (6.5.13);逻辑OR || (6.5.14);条件? (6.5.15);逗号, (6.5.17)。
如果j
为零,那么++i && printf("you can")
将被评估,i
将变为5,you can
也将被打印。你对++大于||的优先级是正确的,但由于有一个序列点,j||
首先是变异的。
答案 1 :(得分:3)
j || ++i && printf("you can")
的计算结果为true,由1
表示。因为它是一个OR,并且因为j非零,所以只评估OR的左手,因此不评估++i
和printf
。因此j
为1,i
保持为4。
当然,真正的代码绝不应该每个人都这样做。您应该始终以操作顺序明显的方式编写代码,并且在OR语句中几乎不应该有代码副作用。
答案 2 :(得分:2)
你在这里有什么:
j = j || ++i && printf("you can");
是一个逻辑表达式(没有数学发生)。让我们分解一下:
++i // as a mathematical expression this is i=i+1 (5 in your case)
printf("you can"); // printf returns the number of chars written, (7)
所以你希望这是:
j = 7 || 5 && 7;
上述表达式的输出只是1.因此即使执行此操作,您也应该看到j=1
。那你为什么不看printf()
输出呢?
原因是整个表达式没有运行。它不必。考虑:
result = TRUE || (anything else);
任何“真实”或与其他任何东西相关的东西都将永远为真。编译器知道这一点,一旦它看到7 ||
,它就等于true ||
并说“我知道,将j设置为true并继续前进”。
这就是为什么表达式不会增加i以及它为什么不打印“你可以”。 现在,如果你要翻转表达式:
j = ++i && printf("you can") || j;
逻辑保持不变,但编译器没有看到||直到评估其他所有内容,所以我将增加并显示printf。
答案 3 :(得分:1)
我用两种方式运行这个程序:
j = j || ++i && printf("you can");
然后,像这样:
j = j || (++i && printf("you can"));
两者的输出均为4 1
。在我运行它们之前,由于逻辑或逻辑的左右关联性,我希望从两者得到完全相同的结果。无论如何,整个表达式将从左到右进行评估。括号的作用是确保将表达式计算为一个表达式,并不一定意味着它将是第一个要计算的表达式。如果您想了解更多证据,可以尝试一些简单的方法:
j = 1 || (++i);
即使(++i)
在括号中,也从不评估它。再次,因为从左到右的相关性。