我正在做复习问题,问我"以下是什么输出,"我在理解这个功能方面遇到了一些麻烦:
int a = 1, b = 1, c = -1;
c = --a && b++;
printf("%d %d %d", a, b, c);
输出为010.我的问题是关于第2行,c = --a && b++
。如何处理此行,以及它如何工作/更改值?如果是c = --a || b++
?从我的理解,我认为输出将是020。
答案 0 :(得分:12)
理解结果的关键概念是short-circuit evaluation布尔运算符(&&
和||
) - 如果在评估布尔运算符的左侧后,该值右侧不能影响整体结果,那么它将不会被评估,它将产生的任何副作用都不会发生。
在第一种情况下,由于--a
评估为0
(= false),因此不评估... && ...
的第二部分,因为“ false AND anything “永远都是假的。具体而言,b++
永远不会被执行,因此其值在输出中保持1
。
在--a || b++
的情况下,整个表达式的值不能由左侧确定(“ false OR something ”仍然可以是真的)所以评估了b++
(它的副作用,递增b
)。
完全理解结果所需的另一个概念是前后增量/减量运算符之间的差异。如果--
或++
在变量之前出现(如--a
中所示),则变量首先递减或递增, new value用于评估整个表达式。如果<{1}}或--
在变量之后出现(如++
中所示),那么变量的当前值将用于评估表达式,并在发生这种情况后发生增量/减量。
应该注意的是,尝试组合同一个变量的b++
/ --
的两个或多个实例的表达式(例如++
)是相当的可能会调用undefined behaviour - 结果可能因平台,编译器,编译器甚至一天中的时间而异。
答案 1 :(得分:6)
在表达式c = --a && b++
中,a
会减少并返回。现在,因为short circuit evaluation而没有评估表达式--a && b++
的第二个参数---一旦我们看到--a==0
我们已经知道表达式将是0
无论是什么是另一个论点---,所以b
保持不变。
a
减少0
而b
仍为1
。
根据您的建议,输出是0 1 0
。
关于第二个问题,如果你写c = --a || b++
,变量a
再次变为零,但表达式仍然可以评估为真 - 因此我们必须评估第二部分,因此执行b++
,返回1
并增加b
。在这种情况下,输出将为0 2 1
,因为c
的值为0 || 1
1
。
简而言之,请阅读
答案 2 :(得分:3)
首先需要关注的是前缀和后缀运算符的属性及其差异。
对于Postfix递增和递减运算符C11
,章节§6.5.2.4,(强调我的)
后缀
++
运算符的结果是操作数的值。作为副作用, 操作数对象的值递增[...]后缀--
运算符类似于后缀++
运算符,除了值为 操作数递减。
对于前缀递增和递减运算符C11
,章节§6.5.3.1,(强调我的)
前缀
++
运算符的操作数的值递增。结果是新的 递增后的操作数的值。 [...]前缀--
运算符类似于前缀++
运算符,但该值除外 操作数递减。
现在,出现了Logical AND(&&
)运算符的属性。从章节§6.5.13开始,(再次强调我的)
&&
运营商保证从左到右的评估; 如果计算第二个操作数,则在评估之间存在一个序列点 第一和第二个操作数。 如果第一个操作数比较等于0,则第二个操作数 操作数未被评估。 [...]
所以,在你的情况下,
int a = 1, b = 1, c = -1;
c = --a && b++;
评估为
c = 0 && .....; // done..., a is decremented to 0,
// so, LHS of && is 0, RHS is not evaluated,
// b remains 1
// and finally, C gets 0.
另一方面,如果使用逻辑OR(||
),那么,根据属性,在章节§6.5.14中提到
[...]
||
运营商保证从左到右的评估;如果 评估第二个操作数,在第一个操作数的评估之间有一个序列点 和第二个操作数。 如果第一个操作数比较不等于0,则第二个操作数为 未评估。
所以,对于案例
int a = 1, b = 1, c = -1;
c = --a || b++;
它将被评估为
c = 0 || 1; //yes, b's value will be used, and then incremented.
所以,
printf("%d %d %d", a, b, c);
将是
0 2 1
答案 3 :(得分:1)
该行:
c = --a && b++;
将a
缩减为0
,因此语句0 && anything else
会导致0
。这就是a
和c
导致0
的原因,因为您似乎已经理解了这一点。
现在让我们看看你没有得到的部分。当a
被评估为0
时,&&
的右侧部分不需要进行评估,因为无论计算出正确部分的值是什么,结果都将是是0
。这意味着b++
将不会被评估,因此b
将保留其初始值。这就是为什么您看到值1
而不是2
,因此输出0 1 0
而不是0 2 0
。
答案 4 :(得分:1)
c = --a && b++;
在第一个--a
被评估,a
变为0
时,只要&&
的1个操作数为false,就不会评估b++
,因此,b
仍为1
,c
为0
。
答案 5 :(得分:1)
b ++根本就不会被执行,因为--a在和条件中评估为false。 由于不需要,它的右侧永远不会被执行。因此,b永远不会增加,因此你不会期望输出。
答案 6 :(得分:-2)
- a:意味着你在行之前减少a。 b ++:执行该行后增加b。这样c(那时)= 0 + 1 = 1;那么:a = 0,b = 2,c = 1;行