Почему этот код всегда производит x=2
?C программирование ++ оператор
unsigned int x = 0;
x++ || x++ || x++ || x++ || ........;
printf("%d\n",x);
Почему этот код всегда производит x=2
?C программирование ++ оператор
unsigned int x = 0;
x++ || x++ || x++ || x++ || ........;
printf("%d\n",x);
1-й x++
изменение х до 1 и возвращает 0
2-го x++
изменения х до 2 и возвращает 1
в этой точке или короткое замыкание, возвращает истину, и оставляет е на 2.
Кстати: unsigned int x = 0; ++ x || ++ x || ++ x || ++ x || ........; printf ("% d \ n", x); даст 1, так как первый ++ x изменит x на 1 и вернет x, произойдет короткое замыкание и ничего больше не будет сделано. – ridecar2
Кстати, я уверен, что это неопределенное поведение. Ваше описание того, почему это даст 2, является правильным, но я не верю, что это будет гарантировано работать таким образом - вы не должны менять переменную более одного раза в выражении. Нельзя увеличивать переменную до тех пор, пока целое выражение завершен, и в этом случае 'x' всегда будет 0. – Chuck
@Chuck: Он определяется, потому что' || 'действует как точка последовательности. (6.5.14/4 в стандарте C99.) – jamesdlin
Из-за short circuit в оценке логического выражения и потому ||
в C и C++, sequence point.
|| является точкой последовательности, так как страница, на которую вы ссылаетесь, упоминает. Так что это не неопределенное поведение. –
Оператор '||' вводит точку последовательности, поэтому выражение не определено. –
Упс, удалено после. пункты от ответа :) –
||
короткое замыкание. Оценивается слева, когда истинное значение найдено (отличное от нуля), оно перестает оценивать, так как выражение теперь истинно и никогда не может быть ложным.
Первый x++
оценивает как 0 (с момента его добавления), от второго до 1, что верно, и presto, все готово!
x ++ || x ++ || x ++ || x ++ || ........;
стараясь заменить ||
с |
.--
Это короткое замыкание логических операторов.
Это та же самая причина, когда вы делаете
if (returns_true() || returns_true()){ }
returns_true
только дозвонились один раз.
Поскольку '||' является точкой последовательности, а '|' не является, если вы замените '||' на '|', вы будете вызывать неопределенное поведение, и это ничего не скажет вам. – jamesdlin
Поскольку логическое ИЛИ замыкает замыкание при обнаружении истины.
Итак, первый x ++ возвращает 0 (false), потому что это пост-инкремент. (x = 1) Второй x ++ возвращает 1 (true) - короткое замыкание. (x = 2)
Печатает x = 2;
Из-за ранней оценки сравнений.
Это эквивалент
0++ | 1++
Компилятор завершает работу сравнения, как только х == 1, то приращение поста, делая х == 2
Является ли это даже компилируемым кодом? – Zano
нет конечно нет. –
Когда вы оценку «а | | b || c || d || e || ... "вы можете прекратить оценку при первом ненулевом значении, которое вы найдете.
Первый «x ++» оценивается в 0 и увеличивает значение x до 1, и оценка выражения продолжается.Второй x ++ оценивается в 1, увеличивается с x на 2, и в этот момент вам не нужно смотреть на остальную часть инструкции OR, чтобы знать, что это будет правдой, поэтому вы остановитесь.
Чтобы быть точным, вы перестаете оценивать первое найденное ненулевое значение. –
Поскольку первый «x ++ || x ++» оценивается как «истинный» (это означает, что он не равен нулю, потому что «0 || 1» истинно. Поскольку все логические операторы OR игнорируются, остальные операции OR игнорируются.
Майк
||
оператор вычисляет выражение левой руки, и если это 0 (ложь), то он будет оценивать выражение правой руки. Если левая рука не 0, то это будет не оценивать правую сторону вообще.
В выражении x++ || x++ || x++ || ...
, первое x++
оценивается; он оценивается в 0, а x увеличивается до 1. Второй оценивается x++
; он оценивается в 1, а x увеличивается до 2. Поскольку второй x++
оценивается с ненулевым значением, ни один из оставшихся x++
выражений не оценивается.
Пахнет домашней работой человека. –
Все еще хороший вопрос, я думаю. В первый момент я подумал, что это неопределенное поведение. Но на самом деле это не так, поскольку '||' является точкой последовательности между левой и правой сторонами. –
FYI: http://en.wikipedia.org/wiki/Sequence_point – jldupont