问题
I am doing review questions which ask me "What is the output of the following," and I am having some trouble understanding something about this function:
int a = 1, b = 1, c = -1;
c = --a && b++;
printf("%d %d %d", a, b, c);
The output is 010. My question is about line 2, c = --a && b++
. How is this line processed, and how does it work/change the values? And if it were c = --a || b++
? From my understanding I thought the output would be 020.
回答1:
The key concept to understanding the result is short-circuit evaluation of Boolean operators (&&
and ||
) -- if, after evaluating the left-hand side of a Boolean operator, the value of the right-hand side cannot affect the overall result, then it will not be evaluated and any side-effects it would produce will not happen.
In the first case, since --a
evaluates to 0
(=false) the second part of ... && ...
is not evaluated, since "false AND anything" will always be false. Specifically, b++
is never executed, and so its value remains 1
in the output.
In the case of --a || b++
, the value of the whole expression cannot be determined by the left-hand side ("false OR something" can still be true) so the b++
is evaluated (and it's side-effect, incrementing b
, happens).
The other concept needed to fully understand the results is the difference between pre- and post-increment/decrement operators. If the --
or ++
appears before the variable (as in --a
) then the variable is decremented or incremented first and new value is used to evaluate the whole expression. If the --
or ++
appears after the variable (as in b++
) then the current value of the variable is used to evaluate the expression and the increment/decrement happens after this has happened.
It should be noted that expressions that try to combine two or more instances of --
/++
of the same variable (e.g. a++ + ++a
) are quite likely to invoke undefined behaviour -- the result may vary by platform, compiler, compiler and even the time of day.
回答2:
In the expression c = --a && b++
, a
gets decreased and returned. Now the second argument of the expression --a && b++
is not evaluated because of short circuit evaluation---once we see that --a==0
we already know that the expression will be 0
regardless of what is the other argument---, so b
remains unchanged.
Decreased a
is 0
and b
remains 1
.
The output is, as you suggest, 0 1 0
.
Regarding the second question, if you write c = --a || b++
, the variable a
again goes to zero but the expression can still evaluate to true---we must thus evaluate the second part as well, thus executing b++
which returns 1
and increases b
. In this case the output would be 0 2 1
, because c
is assigned the value of 0 || 1
which is 1
.
In short, read up on
- pre- and post-increment in C and C++ and on
- short circuit evaluation.
回答3:
The thing you need to focus on here first is the properties of prefix and postfix operators and their differences.
For Postfix increment and decrement operators,
C11
, chapter §6.5.2.4, (emphasis mine)The result of the postfix
++
operator is the value of the operand. As a side effect, the value of the operand object is incremented [...] The postfix--
operator is analogous to the postfix++
operator, except that the value of the operand is decremented.For Prefix increment and decrement operators,
C11
, chapter §6.5.3.1, (emphasis mine)The value of the operand of the prefix
++
operator is incremented. The result is the new value of the operand after incrementation. [...] The prefix--
operator is analogous to the prefix++
operator, except that the value of the operand is decremented.
Now, there comes the property of the Logical AND (&&
) operator. From chapter §6.5.13, (again, emphasis mine)
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 equal to 0, the second operand is not evaluated. [...]
So, in your case,
int a = 1, b = 1, c = -1;
c = --a && b++;
gets evaluated as
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.
On the other hand, if logical OR (||
) would have been used, then, as per the property, mentioned in chapter §6.5.14
[...] 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.
So, for the case
int a = 1, b = 1, c = -1;
c = --a || b++;
it will be evaluated as
c = 0 || 1; //yes, b's value will be used, and then incremented.
So,
printf("%d %d %d", a, b, c);
will be
0 2 1
回答4:
b++ is simply never executed because --a evaluates to false in an and condition. The right side of the and is never executed because not needed. Hence b is never incremented and hence the output you did not expect.
回答5:
c = --a && b++;
In this first --a
is evaulated and a
becomes 0
, as soon as 1 operand of &&
is false , b++
is not evaluated , therefore ,b
remains 1
and c
becomes 0
.
回答6:
The line :
c = --a && b++;
decreases a
to 0
, so the statement 0 && anything else
results to 0
. This is why a
and c
result to 0
, as it seems you have understood.
Now let's see the part you don't get. When a
is evaluated to 0
, the right part of &&
does not need to be evaluated, as no matter what the value of the right part will be calculated to be, the result will be 0
. This means that b++
will not be evaluated and therefore b
will retain its initial value. This is why you see the value 1
instead of 2
, and consequently the output 0 1 0
instead of 0 2 0
.
回答7:
--a : mean you decrease a before do the line. b++: increase b after do the line. so that c ( at that time ) = 0+1 =1; then: a =0, b = 2, c =1; OK
来源:https://stackoverflow.com/questions/36788257/explanation-for-this-functions-output