Комментарии 41
Если по Страуструпу, то выражения должны разбираться таким образом, чтобы получилось как можно большее выражение (по длине) и синтаксически верными, т.е. должно быть (ну это как я думаю) (((++i)++)+i), т.е. 13
0
Конечно в большинстве случаев пробелы не играют роли, но это не тот случай. Выражение должно разобраться именно как (++i)+(++i).
А то что в С++ получается 14, это просто детали реализации модели вычислений (не парсера) конкретного компилятора, насколько я помню, по крайней мере в С, в спецификации строго не оговорено как такое выражение должно вычисляться. И более того, насколько я помню универский курс, в различных компиляторах мы получим различные значения :)
А то что в С++ получается 14, это просто детали реализации модели вычислений (не парсера) конкретного компилятора, насколько я помню, по крайней мере в С, в спецификации строго не оговорено как такое выражение должно вычисляться. И более того, насколько я помню универский курс, в различных компиляторах мы получим различные значения :)
+5
в С++ и Перле 14, в PHP и Яве - 13.
А вообще, это боян.
А вообще вообще, я тоже хотел узнать, почему :-)
А вообще, это боян.
А вообще вообще, я тоже хотел узнать, почему :-)
+1
UPD: главное, что если в С++ или Перле выражение
i = ++i + ++i;
заменить на
i = ++i + ++i + ++i;
то результат будет очень неожиданным!
i = ++i + ++i;
заменить на
i = ++i + ++i + ++i;
то результат будет очень неожиданным!
0
вариант один
1) ++i + ++i (i=5)
2) i + ++i (i=6)
3) i + i (i=7)
вариант два
1) ++i + ++i (i=5)
2) 6 + ++i (i=6)
3) 6 + 7
Внимание вопрос!
Какой вариант правилен?
1) ++i + ++i (i=5)
2) i + ++i (i=6)
3) i + i (i=7)
вариант два
1) ++i + ++i (i=5)
2) 6 + ++i (i=6)
3) 6 + 7
Внимание вопрос!
Какой вариант правилен?
0
В С верен первый вариант. в php - второй. Это особенности языка.
0
многие говорят, что компилятора, а не языка.
0
Дело в том, что си при пре-инкременте увеличение происходит до всего оператора , т.е. в си i = ++i + ++i; это
Итого i=14.
А i=i++ + i++; выдаст 10, если не ошибаюсь, по аналогичной схеме: сначала всё просчитать а потом уж инкрементить. т.е. си отличается ровно на максимализм: либо всё сначала либо всё потом, без промежуточных вариантов.
В php и java ситуация иная: там инкременты происходят там где должны — непосредственно в операции. И мы получаем (при том же i=5):
i=i++ + i++ = 11
или
i=++i + ++i = 13
i=i+2;//двойной инкремент
i=i+i;//уже по 7
Итого i=14.
А i=i++ + i++; выдаст 10, если не ошибаюсь, по аналогичной схеме: сначала всё просчитать а потом уж инкрементить. т.е. си отличается ровно на максимализм: либо всё сначала либо всё потом, без промежуточных вариантов.
В php и java ситуация иная: там инкременты происходят там где должны — непосредственно в операции. И мы получаем (при том же i=5):
i=i++ + i++ = 11
или
i=++i + ++i = 13
+3
как раз пробелы в выражении очени важны, можно переписать выражение так
(++i) + (++i)
(++i) + (++i)
0
Пробелы - whitespace, они не учитываются
0
ISO/IEC 9899:1999 §6.4.1.3:
Preprocessing tokens can be separated by white space; this consists of comments (described later), or white-space characters (space, horizontal tab, new-line, vertical tab, and form-feed), or both. As described in 6.10, in certain circumstances during translation phase 4, white space (or the absence thereof) serves as more than preprocessing token separation. White space may appear within a preprocessing token only as part of a header name or between the quotation characters in a character constant or string literal.
Дальше там объясняется почему x+++++y - это не то же самое что x ++ + ++ y и прочее. C - это не Fortran 66...
Preprocessing tokens can be separated by white space; this consists of comments (described later), or white-space characters (space, horizontal tab, new-line, vertical tab, and form-feed), or both. As described in 6.10, in certain circumstances during translation phase 4, white space (or the absence thereof) serves as more than preprocessing token separation. White space may appear within a preprocessing token only as part of a header name or between the quotation characters in a character constant or string literal.
Дальше там объясняется почему x+++++y - это не то же самое что x ++ + ++ y и прочее. C - это не Fortran 66...
+1
НЛО прилетело и опубликовало эту надпись здесь
С++ предварительно компилирует код! Создается переменная i, с которой и производятся все операции, и даже промежуточные. Вначале выполняет ++i для первого слагаемого (i=5+1=6), затем для второго ++i (i=6+1=7). В итоге получаем переменную i равную 7. И для всего выражения i=7+7=14
0
а зачем такие выражения i = ++i + ++i; ?
давайте тогда писать на BrainFuck
давайте тогда писать на BrainFuck
+1
Ретрище...
Оба результата правильные для своих языков.
Разъяснения в документации
Оба результата правильные для своих языков.
Разъяснения в документации
0
При написании кода следует избегать таких неоднозначных конструкций. Если только вы не хакер и/или не тащитесь от того, что ваш код невозможно разобрать, понять, поддерживать.
ЗЫЖ Ну есть еще, конечно, вариант оптимизации. Но его, как я разумею, здесь не рассматривают.
ЗЫЖ Ну есть еще, конечно, вариант оптимизации. Но его, как я разумею, здесь не рассматривают.
+1
Я тоже думая, что в Си это зависит от компилятора. От конкретной реализации.
Но вообще вариант 14 правильнее. Операция инкремента имеет наиболее высокий приоритет. Она будет выполнена два раза в процессе вычисления выражения. И только потом переменная i будет сложена с собой (не с собой "в прошлом", а с собой сейчас - и это правильно). И результат присвоен ей же.
Так что 14 - логичнее как минимум.
Но вообще вариант 14 правильнее. Операция инкремента имеет наиболее высокий приоритет. Она будет выполнена два раза в процессе вычисления выражения. И только потом переменная i будет сложена с собой (не с собой "в прошлом", а с собой сейчас - и это правильно). И результат присвоен ей же.
Так что 14 - логичнее как минимум.
0
Такой код недопустим.
Во-первых, потому что результаты его выполнения могут быть неопределёнными в языке (лень лезть в определение С, скорее всего, там сказано, что порядок выполнения оперендов в a+b "undefined"; как в остальных наследниках С - надо тоже смотреть, в любом случае см. дальше).
Во-вторых, и это главное, потому что такая конструкция ставит в тупик читающего код.
Во-первых, потому что результаты его выполнения могут быть неопределёнными в языке (лень лезть в определение С, скорее всего, там сказано, что порядок выполнения оперендов в a+b "undefined"; как в остальных наследниках С - надо тоже смотреть, в любом случае см. дальше).
Во-вторых, и это главное, потому что такая конструкция ставит в тупик читающего код.
0
Именно потому что "такая конструкция ставит в тупик читающего код" - такими дебилизмами полны тесты для соискателей на должность Си-программиста во всякие псевдонавороченные софтовые конторы. А-ля "фокус-покус ведет себя не так как выглядит". По-русски говоря - подъебка.
Многие почему-то думают что классный программист должен идеально эмулировать работу препроцессора и компилятора, причем конкретной и любимой нанимателем фирмы.
Многие почему-то думают что классный программист должен идеально эмулировать работу препроцессора и компилятора, причем конкретной и любимой нанимателем фирмы.
0
если мне память не изменяет(хотя я и не уверен в этом =) ) ++i это означает что некоторое число i увеличивается на еденицу (это в "си") . Судя по моим вычислениям должно получиться если i=5, то ответ 12 .Я такого рода вычисления видел в последний раз лет пять назад, так что возможно я и неправ. =))))))
0
Пациент:
- Доктор, я когда делаю так (человек одной рукой пытается достать себе до лопатки, второй тянется к пятке левой ноги и, при этом, встает на носочек правой ноги) у меня вот тут болит. Доктор, что мне делать?
Врач:
- Не делайте так!
- Доктор, я когда делаю так (человек одной рукой пытается достать себе до лопатки, второй тянется к пятке левой ноги и, при этом, встает на носочек правой ноги) у меня вот тут болит. Доктор, что мне делать?
Врач:
- Не делайте так!
+3
Что только люди не делают, лишь бы не читать доки. :)
Итак, правильный ответ: в C/C++ значение этого выражения не определено. Например, в C99 об этом сказано в параграфе 6.5:
2 Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression. Furthermore, the prior value
shall be read only to determine the value to be stored.
В переводе на русский это означает, что неопределенными являются все выражения типа (sequence point у оператора присваивания только одна!):
i = ++i + 1;
a[i++] = i;
Соответственно, вы можете получить абсолютно произвольный результат как на разных компиляторах, так и на одном и том же компиляторе с разными ключами оптимизации. :)
Итак, правильный ответ: в C/C++ значение этого выражения не определено. Например, в C99 об этом сказано в параграфе 6.5:
2 Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression. Furthermore, the prior value
shall be read only to determine the value to be stored.
В переводе на русский это означает, что неопределенными являются все выражения типа (sequence point у оператора присваивания только одна!):
i = ++i + 1;
a[i++] = i;
Соответственно, вы можете получить абсолютно произвольный результат как на разных компиляторах, так и на одном и том же компиляторе с разными ключами оптимизации. :)
+1
РЕТРО! :) Всё зависит от компилятора(интерпритатора). По логике правилен вариант при котором ответ равен 14.
0
sequence point очень занятная тема, но к данному примеру она не имеет отношения.
Тут значение имеет то что получается в результате операции.
В c++ результатом операции ++i является само i, а в java результатом является значние, но не сама переменная. И в вопрос можно сформулировать так: почему приняты настолько разные решения?
Этот конкретный пример врятли напишет в своем коде уважающий себя программист, но, нарпимер, когдато я думал что есть разница между такими вот выражениями:
for (int i=0; i<length; ++i)
for (int i=0; i length; i++)
и в такое заблуждение меня ввел еще университетский курс и всякого рода книжечки. А ведь выполнение ++i или i++ не влияеть на последовательность и количество самого цикла.
Иногда весьма полезно понимать что на что может влиять.
Тут значение имеет то что получается в результате операции.
В c++ результатом операции ++i является само i, а в java результатом является значние, но не сама переменная. И в вопрос можно сформулировать так: почему приняты настолько разные решения?
Этот конкретный пример врятли напишет в своем коде уважающий себя программист, но, нарпимер, когдато я думал что есть разница между такими вот выражениями:
for (int i=0; i<length; ++i)
for (int i=0; i length; i++)
и в такое заблуждение меня ввел еще университетский курс и всякого рода книжечки. А ведь выполнение ++i или i++ не влияеть на последовательность и количество самого цикла.
Иногда весьма полезно понимать что на что может влиять.
0
И еще вопрос. Если эта тема такой большой боян, и все про все уже знают, тогда почему в обсуждении так много разных мнений и неразберихи? Соответственно я не пойму зачем портить автору харизму, не нравится не читайте.
0
Зарегистрируйтесь на Хабре , чтобы оставить комментарий
Превратности вычислений