2010-01-14 8 views
12

Почему этот код всегда производит x=2?C программирование ++ оператор

unsigned int x = 0; 
x++ || x++ || x++ || x++ || ........; 
printf("%d\n",x); 
+10

Пахнет домашней работой человека. –

+2

Все еще хороший вопрос, я думаю. В первый момент я подумал, что это неопределенное поведение. Но на самом деле это не так, поскольку '||' является точкой последовательности между левой и правой сторонами. –

+0

FYI: http://en.wikipedia.org/wiki/Sequence_point – jldupont

ответ

30

1-й x++ изменение х до 1 и возвращает 0
2-го x++ изменения х до 2 и возвращает 1

в этой точке или короткое замыкание, возвращает истину, и оставляет е на 2.

+2

Кстати: unsigned int x = 0; ++ x || ++ x || ++ x || ++ x || ........; printf ("% d \ n", x); даст 1, так как первый ++ x изменит x на 1 и вернет x, произойдет короткое замыкание и ничего больше не будет сделано. – ridecar2

+1

Кстати, я уверен, что это неопределенное поведение. Ваше описание того, почему это даст 2, является правильным, но я не верю, что это будет гарантировано работать таким образом - вы не должны менять переменную более одного раза в выражении. Нельзя увеличивать переменную до тех пор, пока целое выражение завершен, и в этом случае 'x' всегда будет 0. – Chuck

+12

@Chuck: Он определяется, потому что' || 'действует как точка последовательности. (6.5.14/4 в стандарте C99.) – jamesdlin

9

Из-за short circuit в оценке логического выражения и потому || в C и C++, sequence point.

+0

|| является точкой последовательности, так как страница, на которую вы ссылаетесь, упоминает. Так что это не неопределенное поведение. –

+0

Оператор '||' вводит точку последовательности, поэтому выражение не определено. –

+0

Упс, удалено после. пункты от ответа :) –

5

|| короткое замыкание. Оценивается слева, когда истинное значение найдено (отличное от нуля), оно перестает оценивать, так как выражение теперь истинно и никогда не может быть ложным.

Первый x++ оценивает как 0 (с момента его добавления), от второго до 1, что верно, и presto, все готово!

11

x ++ || x ++ || x ++ || x ++ || ........;

  • Первый x ++ сначала оценивает 0 для условной проверки, за которым следует приращение. Итак, первое условие терпит неудачу, но x получает приращение на 1.
  • Теперь оценивается второй x ++, который оценивается в 1 для условной проверки, а x получает приращение до 2. Так как выражение оценивается как 1 (true), нет нужно идти дальше.
0

стараясь заменить || с | .--

Это короткое замыкание логических операторов.

Это та же самая причина, когда вы делаете

if (returns_true() || returns_true()){ } 

returns_true только дозвонились один раз.

+2

Поскольку '||' является точкой последовательности, а '|' не является, если вы замените '||' на '|', вы будете вызывать неопределенное поведение, и это ничего не скажет вам. – jamesdlin

1

Поскольку логическое ИЛИ замыкает замыкание при обнаружении истины.

Итак, первый x ++ возвращает 0 (false), потому что это пост-инкремент. (x = 1) Второй x ++ возвращает 1 (true) - короткое замыкание. (x = 2)

Печатает x = 2;

1

Из-за ранней оценки сравнений.

Это эквивалент

0++ | 1++ 

Компилятор завершает работу сравнения, как только х == 1, то приращение поста, делая х == 2

+0

Является ли это даже компилируемым кодом? – Zano

+1

нет конечно нет. –

2

Когда вы оценку «а | | b || c || d || e || ... "вы можете прекратить оценку при первом ненулевом значении, которое вы найдете.

Первый «x ++» оценивается в 0 и увеличивает значение x до 1, и оценка выражения продолжается.Второй x ++ оценивается в 1, увеличивается с x на 2, и в этот момент вам не нужно смотреть на остальную часть инструкции OR, чтобы знать, что это будет правдой, поэтому вы остановитесь.

+0

Чтобы быть точным, вы перестаете оценивать первое найденное ненулевое значение. –

1

Поскольку первый «x ++ || x ++» оценивается как «истинный» (это означает, что он не равен нулю, потому что «0 || 1» истинно. Поскольку все логические операторы OR игнорируются, остальные операции OR игнорируются.

Майк

1

|| оператор вычисляет выражение левой руки, и если это 0 (ложь), то он будет оценивать выражение правой руки. Если левая рука не 0, то это будет не оценивать правую сторону вообще.

В выражении x++ || x++ || x++ || ..., первое x++ оценивается; он оценивается в 0, а x увеличивается до 1. Второй оценивается x++; он оценивается в 1, а x увеличивается до 2. Поскольку второй x++ оценивается с ненулевым значением, ни один из оставшихся x++ выражений не оценивается.