2016-04-22 3 views
4

Я делаю обзор вопросов, которые задают мне «Какой выход из следующих» и у меня возникли некоторые проблемы понимания что-то об этой функции:Объяснение для вывода этой функции

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

Узнайте о свойствах оператора pre и post in/decament. –

+1

Прежде чем добавить ответ, обратите внимание на то, что '--a && b ++' коротких замыканий. – Schwern

ответ

6

В выражении c = --a && b++, a уменьшается и возвращается. Теперь второй аргумент выражения --a && b++ не вычисляется из short circuit evaluation --- когда мы видим, что --a==0 мы уже знаем, что выражение будет 0независимо того, что другой аргумент ---, так b остается неизменным.

Понижено a is 0 и b остается 1.

Выходной сигнал, как вы предлагаете, 0 1 0.

Что касается второго вопроса, если вы пишете c = --a || b++, переменная a снова стремится к нулю, но выражение все еще можно оценить, верно --- мы должны таким образом оценить вторую часть, а, таким образом, выполняя b++, который возвращает 1 и увеличивает b. В этом случае выход будет 0 2 1, потому что c присваивается значение 0 || 1, которое равно 1.

Короче говоря, читать на

+0

'0 1 0' http://ideone.com/48B9wk – weston

+0

Да, из-за [оценки короткого замыкания] (https://en.wikipedia.org/wiki/Short-circuit_evaluation); Я обновил ответ – blazs

+1

Недостающий кусок - короткие замыкания '--a && b ++'. '--a' false, поэтому' b ++ 'никогда не выполняется. – Schwern

-2

--a: означает, что вы уменьшите a до линии. b ++: увеличить b после строки. так что c (в это время) = 0 + 1 = 1; то: a = 0, b = 2, c = 1; OK

+0

Да, это то, чего они ожидают, но это '0 1 0' http://ideone.com/48B9wk – weston

+0

О, я неправильно понимаю && с +. – chickensoup

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.

3

В первую очередь вам нужно сосредоточиться на свойствах операторов префикса и постфикса и их различий.

  • Для Postfix инкремента и декремента, C11, глава §6.5.2.4, (курсив мой )

    Результат оператора постфикса ++ это значение операнда. В качестве побочного эффекта значение объекта операнда увеличивается [...] Оператор postfix -- аналогичен оператору postfix ++, за исключением того, что значение операнд уменьшается.

  • Для префиксных инкремента и декремента, C11, глава §6.5.3.1, (курсив мой )

    Значение операнда оператора префикса ++ увеличивается. В результате получается новое значение 0ABоперанда после инкремента. [...] Оператор префикса -- аналогичен оператору префикса ++, за исключением того, что значение операнда уменьшено.

Теперь приходит свойство логического И (&&) оператора. Из главы §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. 

С другой стороны, если логическое ИЛИ (||) были бы использованы , то, согласно собственности, упомянутой в главе 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 
1
c = --a && b++; 

В этом первом --a является evaulated и a становится 0, как только один операнд && является ложным, b++ не вычисляется, таким образом, остается b1 и c становится 0.

11

Ключевое понятие для понимания результата является short-circuit evaluation булевых операторы (&& и ||) - если после оценки левых булевого оператора, значение правой не может повлиять на общем результат, то он не будет оценен и никаких побочных эффектов, которые он произведет, не произойдет.

В первом случае, так как --a вычисляется в 0 (= FALSE) вторая часть ... && ... не вычисляется, так как «ложно и что-нибудь» всегда будет ложным. В частности, b++ никогда не выполняется, поэтому его значение остается на выходе 1.

В случае --a || b++, значение всего выражения не может быть определена с помощью левой стороны («ложь или что-то» все еще может быть правдой), так что b++является оценена (и это побочный эффект, приращение b, бывает).

Другая концепция, необходимая для полного понимания результатов, - это разница между операторами до и после инкремента/декремента. Если -- или ++ отображается до, переменная (как в --a), тогда переменная уменьшается или увеличивается в первом порядке, а значение новое значение используется для оценки всего выражения. Если -- или ++ появляется после переменной (как и в b++), то ток значения переменного используются для вычисления выражения и увеличение/уменьшение происходит после того, как это произошло.

Следует отметить, что выражения, которые пытаются объединить два или несколько экземпляров из --/++той же переменной (например, a++ + ++a), весьма вероятно, вызвать undefined behaviour - результат может варьироваться в зависимости от платформы, компилятор, компилятор и даже время суток.

+3

, полный ответ должен предпочтительно касаться разницы между пре-и пост-приращением – sp2danny

1

b ++ просто не выполняется, потому что --a оценивает значение false в состоянии an. Правая сторона и никогда не выполняется, потому что не требуется. Следовательно, b никогда не увеличивается и, следовательно, результат, которого вы не ожидали.

Смежные вопросы