此函数输出的说明

时间:2016-04-22 08:03:44

标签: c output logical-operators integer-arithmetic

我正在做复习问题,问我"以下是什么输出,"我在理解这个功能方面遇到了一些麻烦:

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。

7 个答案:

答案 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减少0b仍为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。这就是ac导致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仍为1c0

答案 5 :(得分:1)

b ++根本就不会被执行,因为--a在和条件中评估为false。 由于不需要,它的右侧永远不会被执行。因此,b永远不会增加,因此你不会期望输出。

答案 6 :(得分:-2)

- a:意味着你在行之前减少a。 b ++:执行该行后增加b。这样c(那时)= 0 + 1 = 1;那么:a = 0,b = 2,c = 1;行