![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| val |
|
|||
![]() Program developer ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 992 Регистрация: 14.1.2003 Где: г. Киев Репутация: нет Всего: 7 |
Угадайте с двух раз, какое значение получит переменная с, 47 или 117, после такого вычисления
Сначала подумайте! Будьте честными перед собой и товарищами! Потом я расскажу про проблемы портирования, связанные с этим выражением... -------------------- Терпимость - величайшее благо человечества... Ярчайший признак интеллекта – постоянно хорошее настроение… |
|||
|
||||
| maxim1000 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 17 Всего: 110 |
47
Добавлено @ 17:15 это я так...просто... а вообще, если по-умному, надо бы в стандарт заглянуть... -------------------- qqq |
|||
|
||||
| val |
|
|||
![]() Program developer ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 992 Регистрация: 14.1.2003 Где: г. Киев Репутация: нет Всего: 7 |
Ну, какие еще варианты?
-------------------- Терпимость - величайшее благо человечества... Ярчайший признак интеллекта – постоянно хорошее настроение… |
|||
|
||||
| Enflout |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 260 Регистрация: 22.5.2004 Репутация: нет Всего: 6 |
117
Вычисляем то справа налево вроде. |
|||
|
||||
| maxim1000 |
|
||||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 17 Всего: 110 |
и действительно, какие же еще могут быть варианты -------------------- qqq |
||||||
|
|||||||
| setq |
|
|||
|
Unregistered |
это не определяется стандартом языка. вот моё ИМХО. (читай: зависит от компилятора)
|
|||
|
||||
| val |
|
||||
![]() Program developer ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 992 Регистрация: 14.1.2003 Где: г. Киев Репутация: нет Всего: 7 |
Вообще порядок вычислении определяется приоритетом операций... Даю подсказку: скобки имеют самый высокий приоритет... -------------------- Терпимость - величайшее благо человечества... Ярчайший признак интеллекта – постоянно хорошее настроение… |
||||
|
|||||
| chipset |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4071 Регистрация: 11.1.2003 Где: Seattle, US Репутация: 27 Всего: 165 |
117 помойму.
--------------------
|
|||
|
||||
| val |
|
|||
![]() Program developer ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 992 Регистрация: 14.1.2003 Где: г. Киев Репутация: нет Всего: 7 |
да, на самом деле, правильный ответ именно 117, только вот почему такие компиляторы как VC++, Borland C++, gcc дают 47 не понятно...
Любопытно, что при включенной оптимазации на VC++ получаем тоже 117... Добавлено @ 17:45 И как тут возможно корректное портирование?! -------------------- Терпимость - величайшее благо человечества... Ярчайший признак интеллекта – постоянно хорошее настроение… |
|||
|
||||
| chipset |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 4071 Регистрация: 11.1.2003 Где: Seattle, US Репутация: 27 Всего: 165 |
Я думаю что таких ситуаций вообще следует избегать, также как и:
i+++i; Undefined behavior короче (умничаю). --------------------
|
|||
|
||||
| maxim1000 |
|
||||||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 17 Всего: 110 |
я, к сожалению, не знаю, как реализовано вычисление подобных выражений в компиляторе, но знаю, как его в принципе можно организовать:
1. для интерпретаторов: делаем стек значений и стек операций идем слева направо если встречаем значение (или переменную, которую мы заменяем на ее значение) отсылаем ее в стек значений, если операцию - в стек операций если мы видим, что операция с более низким приоритетом идет после операции с более высоким приоритетом, выполняем ту, которая с более высоким (при этом значения достаются из стека, участвуют в выполнении операции, а результат отправляется назад в стек) со скобками посложнее: у открывающей скобки самый высокий приоритет, у закрывающей - самы низкий это дает такую последовательность: когда доходим до начала выражения в скобках, его значение не будет использовано, пока не будет вычислено до конца когда доходим до конца выражения в скобках, все операции внутри него будут выполнены когда встречаются просто открывающая и закрывающая скобки, они просто схлопываются и остается нужное число фукции реализуются похожим образом, только перед схлопыванием выполняется некоторый код во-о-от... 2. для компиляторов: отличие состоит в том, чтобы как можно больше дел сделать на этапе компиляции и оставить на исполнение минимум операций отсюда получаем: все, что можно посчитать уже сейчас (константы всякие) - посчитать стек операций - убрать, заменив его на простую последовательность операций (которая уже известна) получаем просто код, представляющий из себя три типа операций: 1. записать значение в стек 2. прочитать значение из стека 3. выполнить операцию (арифметическую или функцию) а теперь - как я размышлял, когда отвечал на вопрос: последовательность вычислений такая: 1. a -> стек 2. видим умножение, но не выполняем, т.к. не знаем, что там дальше 3. b -> стек 4. видим "-", значит, умножение надо выполнять 5. a,b <- стек 6. a*b -> стек 7. 36 -> стек 8. видим деление и понимаем: 8.1. вычитание выполнять не стоит, т.к. сначала надо будет выполнить деление 8.2. деление тоже выполнять рановато (т.к. неизвестно, что дальше) 9. видим скобки - радуемся, что не выполнили деление 10. видим функцию operator=( (&a) , (b+2) ) (а вы что думали --. операция &a - на самом деле такое же значение, как и любое другое 11. &a ->стек 12. видим открывающую скобку 13. b -> стек 14. видим + 15. 2 -> стек 16. видим закрывающую скобку - выполняем плюс 17. b,2 <- стек, b+2 -> стек 18. видим еще одну закрывающую скобку - надо выполнить функцию 19. (&a), (b+2) <- стек 20. выполняем функцию operator= 21. результат -> стек 22. у нас осталось деление - выполняем 23. осталось вычитание - выполняем Добавлено @ 17:57 ого... тут уже написали кучу всего Добавлено @ 18:00
источник, если можно... стандарт? если нет, то это все - такие же домыслы, как и то, что я написал
вот мое сообщение - версия ответа на этот вопрос
если портирование соответствует стандарту - оно корректное если нет - то нет другой вопрос: нужно ли корректное портирование или портирование с учетом компилятора исходного кода Добавлено @ 18:01 УЖАС...посмотрел, сколько, оказывается, я написал...УЖАС... -------------------- qqq |
||||||
|
|||||||
| setq |
|
|||
|
Unregistered |
приоритет операций вещь хорошая, но что выполнится первым: f() или g() ?
впрочем про && и || известно, что они вычисляют свой левый аргумент раньше правого. боюсь, это всё на что можно рассчитывать. если чего-то не понял - объясните. |
|||
|
||||
| versus |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 69 Регистрация: 8.3.2005 Где: Переславль-Залесс кий Репутация: нет Всего: 3 |
chipset, согласен, undefined behavior. Стандарт не фиксирует в каком порядке будут вычисляться операнды оператора '-' (равно как и +, *, и / и другие, последовательность вычислений фиксируется только для '&&', '||', ',' и '?:'). Скобки здесь никак не влиють на последовательность в котором будут вычислены эти выражения.
|
|||
|
||||
| Goryachev |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 67 Регистрация: 23.2.2005 Где: Израиль Репутация: нет Всего: нет |
Я не понимаю, почему в VC++ и в BC++ дает 47, но по стандартному приоритету операторов, должно быть 117.
|
|||
|
||||
| bel_nikita |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Эксперт Сообщений: 2304 Регистрация: 12.10.2003 Где: Поезд №21/22 ( ст . Прага ) Репутация: 21 Всего: 47 |
упс-сс
Это сообщение отредактировал(а) bel_nikita - 9.3.2005, 21:10 |
|||
|
||||
| Дрон |
|
||||||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 10 Всего: 93 |
А в чём заключается стандартный приоритет операторов? Обычно всё вычисляется слева направо, кроме присваивания и ещё какого-то действия (сейчас в хелпы гляну) Добавлено @ 21:39 Вот: Таблица приоритетов из борландовского хелпа.
Добавлено @ 21:41 Так что я бы сказал, что 47. Добавлено @ 21:44 Насчёт стандартов
-------------------- Да. Именно так. |
||||||
|
|||||||
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: 2 Всего: 18 |
Умножение, потом вычитание деления, так что вполне логично Итак, опять пришел к вопросу "что же правильно?" |
|||
|
||||
| versus |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 69 Регистрация: 8.3.2005 Где: Переславль-Залесс кий Репутация: нет Всего: 3 |
видимо правильно будет не писать такой код вовсе :-)
|
|||
|
||||
| maxim1000 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 17 Всего: 110 |
хм...а почему это знаменатель должен вычисляться раньше? все просто - есть последняя операция - вычитание для ее выполнения нужно посчитать левый аргемент и правый и никакие приоритеты и скобки (по крайней мере, с точки зрения математики) не могут указать порядка их вычисления Добавлено @ 11:12 хоть параллельно -------------------- qqq |
|||
|
||||
| Fantasist |
|
||||||||||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: 4 Всего: 41 |
Как и сказал chipset, правильно здесь - undefined behavior. И это по стандарту.
То есть компилятор волен выбирать сам, что ему вначале вычислять a*b или (a=b+2). Приоритет играет роль только тогда, когда операции зависимы друг от друга, здесь же оба слагаемых можно вычислять в каком угодно порядке - от перестановки слагаемых сумма не изменяется.
Не фига.
Портирование некорректных выражений не может быть корректным никак.
Нет тут никакого стандартного приоритета операций. Если я напишу так:
ничего не измениться. Добавлено @ 04:01
Именно! -------------------- Волны гасят ветер... |
||||||||||
|
|||||||||||
| Mysterio |
|
|||
![]() Планирующий ![]() Профиль Группа: Участник Сообщений: 66 Регистрация: 28.12.2004 Репутация: нет Всего: нет |
В книжках пишут,что компилятор(в моем случ.BC311) проходит в два захода. Причем в первом('заход присваивания') приоритеты распределяются по принципу нарастания операций. Т.е. последнее, что он "помнит" есть небольшое выражение a=(b+2) для последующих операций над переменными во втором заходе. И получается именно 117. Насчет VC++ я считаю, что там проходы компилятора организованы несколько иначе. Может кто знает?
|
|||
|
||||
| val |
|
||||
![]() Program developer ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 992 Регистрация: 14.1.2003 Где: г. Киев Репутация: нет Всего: 7 |
Нет, товарищи, именно правильный ответ 117. Всё остальное глюки компиляторов. Я проверил на последних версиях DOT NETа и проконсультировался с экспертами по С-спецификации, именно так и есть. Сначала вычисляется всё то, что в самых вложенных скобках и так далее...
исключительно с точки зрения математики, но ни как разбора выражения компилятором. Еще раз говорю, что первым делом компилятор ставит на исполнение выражение в самых вложенных скобках... Добавлено @ 10:26 Алгоритм разбора обратной польской записи тому пример... -------------------- Терпимость - величайшее благо человечества... Ярчайший признак интеллекта – постоянно хорошее настроение… |
||||
|
|||||
| Fantasist |
|
||||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: 4 Всего: 41 |
Приведи пожалуйста цитаты (или хотя бы параграфы) из стандарта С++(или С), которые бы утверждали, что это выражение должно вычислятся таким образом. Еще тогда попробуй откомпилировать такое выражение: с = (1*(a*b)) - 36 / (a=(b+2)) Поменяется ли результат? А вот так: с = -( 36 / (a=(b+2))) +( (1*(a*b)) )
Компилятор должен соотвествовать стандарту языка, если он его выполняет, то все остальное он может делать по своему усмотрению. Это сообщение отредактировал(а) Fantasist - 11.3.2005, 23:04 -------------------- Волны гасят ветер... |
||||
|
|||||
| Fantasist |
|
||||||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: 4 Всего: 41 |
Или еще лучше, возьмем два выражения:
и
Теперь во втором случае "самые вложенные скобки" - это a*b. Значит по твоему утверждению эти два выражения должны давать разные результаты. Давай скомпилируй и убедись. Добавлено @ 23:06
Никакой алгоритм разборе не стандартизирован для использования, а потому использовать компилятор может что хочет. -------------------- Волны гасят ветер... |
||||||
|
|||||||
| Fantasist |
|
|||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: 4 Всего: 41 |
Ну что, вопросов больше нет?
Это сообщение отредактировал(а) Fantasist - 15.3.2005, 18:07 -------------------- Волны гасят ветер... |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |