Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Угадайте, что получиться... Знатокам С... 
:(
    Опции темы
val
  Дата 9.3.2005, 17:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: нет
Всего: 7



Угадайте с двух раз, какое значение получит переменная с, 47 или 117, после такого вычисления
Код

a=5; 
b=10;
с = a*b - 36 / (a=(b+2));


Сначала подумайте! Будьте честными перед собой и товарищами!

Потом я расскажу про проблемы портирования, связанные с этим выражением...



--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
maxim1000
Дата 9.3.2005, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



47
Добавлено @ 17:15
это я так...просто... smile
а вообще, если по-умному, надо бы в стандарт заглянуть...


--------------------
qqq
PM WWW   Вверх
val
Дата 9.3.2005, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: нет
Всего: 7



Ну, какие еще варианты?


--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
Enflout
Дата 9.3.2005, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 260
Регистрация: 22.5.2004

Репутация: нет
Всего: 6



117
Вычисляем то справа налево вроде. smile
PM MAIL   Вверх
maxim1000
Дата 9.3.2005, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



Цитата(val @ 9.3.2005, 15:01)
какое значение получит переменная с, 47 или 117

Цитата(maxim1000 @ 9.3.2005, 15:15)
47

Цитата(val @ 9.3.2005, 15:21)
Ну, какие еще варианты?

и действительно, какие же еще могут быть варианты smile


--------------------
qqq
PM WWW   Вверх
setq
Дата 9.3.2005, 17:28 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











это не определяется стандартом языка. вот моё ИМХО. (читай: зависит от компилятора)
  Вверх
val
Дата 9.3.2005, 17:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: нет
Всего: 7



Цитата
это не определяется стандартом языка. вот моё ИМХО. (читай: зависит от компилятора)


Цитата
Вычисляем то справа налево вроде


Вообще порядок вычислении определяется приоритетом операций...
Даю подсказку: скобки имеют самый высокий приоритет...


--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
chipset
Дата 9.3.2005, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 165



117 помойму.


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
val
Дата 9.3.2005, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: нет
Всего: 7



да, на самом деле, правильный ответ именно 117, только вот почему такие компиляторы как VC++, Borland C++, gcc дают 47 не понятно...

Любопытно, что при включенной оптимазации на VC++ получаем тоже 117...

Добавлено @ 17:45
И как тут возможно корректное портирование?!


--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
chipset
Дата 9.3.2005, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

Репутация: 27
Всего: 165



Я думаю что таких ситуаций вообще следует избегать, также как и:
i+++i;
Undefined behavior короче (умничаю).


--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
maxim1000
Дата 9.3.2005, 17:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



я, к сожалению, не знаю, как реализовано вычисление подобных выражений в компиляторе, но знаю, как его в принципе можно организовать:
1. для интерпретаторов: делаем стек значений и стек операций
идем слева направо
если встречаем значение (или переменную, которую мы заменяем на ее значение) отсылаем ее в стек значений, если операцию - в стек операций
если мы видим, что операция с более низким приоритетом идет после операции с более высоким приоритетом, выполняем ту, которая с более высоким (при этом значения достаются из стека, участвуют в выполнении операции, а результат отправляется назад в стек)
со скобками посложнее: у открывающей скобки самый высокий приоритет, у закрывающей - самы низкий smile
это дает такую последовательность: когда доходим до начала выражения в скобках, его значение не будет использовано, пока не будет вычислено до конца
когда доходим до конца выражения в скобках, все операции внутри него будут выполнены
когда встречаются просто открывающая и закрывающая скобки, они просто схлопываются и остается нужное число
фукции реализуются похожим образом, только перед схлопыванием выполняется некоторый код
во-о-от...
2. для компиляторов: отличие состоит в том, чтобы как можно больше дел сделать на этапе компиляции и оставить на исполнение минимум операций
отсюда получаем:
все, что можно посчитать уже сейчас (константы всякие) - посчитать
стек операций - убрать, заменив его на простую последовательность операций (которая уже известна)
получаем просто код, представляющий из себя три типа операций:
1. записать значение в стек
2. прочитать значение из стека
3. выполнить операцию (арифметическую или функцию)

а теперь - как я размышлял, когда отвечал на вопрос:
последовательность вычислений такая:
1. a -> стек
2. видим умножение, но не выполняем, т.к. не знаем, что там дальше
3. b -> стек
4. видим "-", значит, умножение надо выполнять
5. a,b <- стек
6. a*b -> стек
7. 36 -> стек
8. видим деление и понимаем:
8.1. вычитание выполнять не стоит, т.к. сначала надо будет выполнить деление
8.2. деление тоже выполнять рановато (т.к. неизвестно, что дальше)
9. видим скобки - радуемся, что не выполнили деление smile
10. видим функцию operator=( (&a) , (b+2) ) (а вы что думали smile)
--. операция &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
Цитата
да, на самом деле, правильный ответ именно 117

источник, если можно...
стандарт?
если нет, то это все - такие же домыслы, как и то, что я написал smile
Цитата
только вот почему такие компиляторы как VC++, Borland C++, gcc дают 47 не понятно...

вот мое сообщение - версия ответа на этот вопрос
Цитата
И как тут возможно корректное портирование?!

если портирование соответствует стандарту - оно корректное smile
если нет - то нет
другой вопрос: нужно ли корректное портирование или портирование с учетом компилятора исходного кода
Добавлено @ 18:01
УЖАС...посмотрел, сколько, оказывается, я написал...УЖАС...


--------------------
qqq
PM WWW   Вверх
setq
Дата 9.3.2005, 18:19 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











приоритет операций вещь хорошая, но что выполнится первым: f() или g() ?
Код
f() + g()
с точки зрения таблицы приоритетов операций это никак не определяется. а нет в стандарте - зелёный свет разработчикам компиляторов: делай как хочешь.

впрочем про && и || известно, что они вычисляют свой левый аргумент раньше правого. боюсь, это всё на что можно рассчитывать.

если чего-то не понял - объясните.
  Вверх
versus
Дата 9.3.2005, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 69
Регистрация: 8.3.2005
Где: Переславль-Залесс кий

Репутация: нет
Всего: 3



chipset, согласен, undefined behavior. Стандарт не фиксирует в каком порядке будут вычисляться операнды оператора '-' (равно как и +, *, и / и другие, последовательность вычислений фиксируется только для '&&', '||', ',' и '?:'). Скобки здесь никак не влиють на последовательность в котором будут вычислены эти выражения.
PM MAIL WWW   Вверх
Goryachev
Дата 9.3.2005, 20:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 67
Регистрация: 23.2.2005
Где: Израиль

Репутация: нет
Всего: нет



Я не понимаю, почему в VC++ и в BC++ дает 47, но по стандартному приоритету операторов, должно быть 117.
PM MAIL   Вверх
bel_nikita
Дата 9.3.2005, 20:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

Репутация: 21
Всего: 47



упс-сс smile

Это сообщение отредактировал(а) bel_nikita - 9.3.2005, 21:10


--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
Дрон
Дата 9.3.2005, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 10
Всего: 93



Цитата(Goryachev @ 9.3.2005, 20:28)
но по стандартному приоритету операторов, должно быть 117

А в чём заключается стандартный приоритет операторов?
Обычно всё вычисляется слева направо, кроме присваивания и ещё какого-то действия (сейчас в хелпы гляну)
Добавлено @ 21:39
Вот:
Таблица приоритетов из борландовского хелпа.
Код
()    []    ->    ::    .                            left to right
! ~ + -    ++ -- & * sizeof new delete                right to left
.*    ->*                                        left to right
*    /    %                                    left to right
+    -                                          left to right
<<    >>                                           left to right
<    <=    >    >=                                left to right
==    !=                                        left to right
&                                               left to right
^                                               left to right
|                                                left to right
&&                                              left to right
||                                                right to left
?:                                                left to right
= *= /=    %= +=    -= &=    ^= |=  <<= >>=         right to left
,                                                left to right
(причём во второй строчке операции "+" и "-" -- унарные.
Добавлено @ 21:41
Так что я бы сказал, что 47.
Добавлено @ 21:44
Насчёт стандартов smile
Цитата
Order of operations is not defined by the language. The compiler is free to evaluate such expressions in any order, if the compiler can guarantee a consistent result



--------------------
Да. Именно так.
PM   Вверх
Fixin
Дата 9.3.2005, 22:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ёжик
***


Профиль
Группа: Комодератор
Сообщений: 1357
Регистрация: 6.1.2004

Репутация: 2
Всего: 18



Цитата
вот почему такие компиляторы как VC++, Borland C++, gcc дают 47 не понятно...

Умножение, потом вычитание деления, так что вполне логично smile . Хотя, если представить себя парсером, то получается 117 smile .
Итак, опять пришел к вопросу "что же правильно?" smile
PM MAIL ICQ   Вверх
versus
Дата 10.3.2005, 02:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 69
Регистрация: 8.3.2005
Где: Переславль-Залесс кий

Репутация: нет
Всего: 3



видимо правильно будет не писать такой код вовсе :-)
PM MAIL WWW   Вверх
maxim1000
Дата 10.3.2005, 11:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



Цитата
если представить себя парсером, то получается 117

хм...а почему это знаменатель должен вычисляться раньше?
все просто - есть последняя операция - вычитание
для ее выполнения нужно посчитать левый аргемент и правый
и никакие приоритеты и скобки (по крайней мере, с точки зрения математики) не могут указать порядка их вычисления
Добавлено @ 11:12
хоть параллельно


--------------------
qqq
PM WWW   Вверх
Fantasist
Дата 11.3.2005, 03:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: 4
Всего: 41



Как и сказал chipset, правильно здесь - undefined behavior. И это по стандарту.
То есть компилятор волен выбирать сам, что ему вначале вычислять a*b или (a=b+2). Приоритет играет роль только тогда, когда операции зависимы друг от друга, здесь же оба слагаемых можно вычислять в каком угодно порядке - от перестановки слагаемых сумма не изменяется.


Цитата(val @ 9.3.2005, 14:44)
да, на самом деле, правильный ответ именно 117


Не фига. smile Правильный ответ дан выше.

Цитата(val @ 9.3.2005, 14:44)
И как тут возможно корректное портирование?!


Портирование некорректных выражений не может быть корректным никак.



Цитата(Goryachev @ 9.3.2005, 17:28)
Я не понимаю, почему в VC++ и в BC++ дает 47, но по стандартному приоритету операторов, должно быть 117.


Нет тут никакого стандартного приоритета операций. Если я напишу так:
Код

с = (a*b) - (36 / (a=(b+2)) );

или

с = - (36 / (a=(b+2)) )+(a*b);



ничего не измениться.

Добавлено @ 04:01
Цитата(versus @ 9.3.2005, 23:14)
видимо правильно будет не писать такой код вовсе :-)


Именно!


--------------------
Волны гасят ветер...
PM MAIL   Вверх
Mysterio
Дата 11.3.2005, 10:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Планирующий
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 28.12.2004

Репутация: нет
Всего: нет



В книжках пишут,что компилятор(в моем случ.BC311) проходит в два захода. Причем в первом('заход присваивания') приоритеты распределяются по принципу нарастания операций. Т.е. последнее, что он "помнит" есть небольшое выражение a=(b+2) для последующих операций над переменными во втором заходе. И получается именно 117. Насчет VC++ я считаю, что там проходы компилятора организованы несколько иначе. Может кто знает?
PM MAIL   Вверх
val
Дата 11.3.2005, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Program developer
**


Профиль
Группа: Участник Клуба
Сообщений: 992
Регистрация: 14.1.2003
Где: г. Киев

Репутация: нет
Всего: 7



Цитата
Цитата (val @ 9.3.2005, 14:44)
да, на самом деле, правильный ответ именно 117



Не фига.  Правильный ответ дан выше.


Нет, товарищи, именно правильный ответ 117. Всё остальное глюки компиляторов. Я проверил на последних версиях DOT NETа и проконсультировался с экспертами по С-спецификации, именно так и есть. Сначала вычисляется всё то, что в самых вложенных скобках и так далее...

Цитата
и никакие приоритеты и скобки (по крайней мере, с точки зрения математики) не могут указать порядка их вычисления


исключительно с точки зрения математики, но ни как разбора выражения компилятором. Еще раз говорю, что первым делом компилятор ставит на исполнение выражение в самых вложенных скобках...


Добавлено @ 10:26
Алгоритм разбора обратной польской записи тому пример...


--------------------
Терпимость - величайшее благо человечества...
Ярчайший признак интеллекта – постоянно хорошее настроение…
PM MAIL ICQ   Вверх
Fantasist
Дата 11.3.2005, 22:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: 4
Всего: 41



Цитата(val @ 11.3.2005, 07:25)
Нет, товарищи, именно правильный ответ 117. Всё остальное глюки компиляторов.


Приведи пожалуйста цитаты (или хотя бы параграфы) из стандарта С++(или С), которые бы утверждали, что это выражение должно вычислятся таким образом.

Еще тогда попробуй откомпилировать такое выражение:

с = (1*(a*b)) - 36 / (a=(b+2))

Поменяется ли результат? А вот так:

с = -( 36 / (a=(b+2))) +( (1*(a*b)) )

Цитата(val @ 11.3.2005, 07:25)
исключительно с точки зрения математики, но ни как разбора выражения компилятором.


Компилятор должен соотвествовать стандарту языка, если он его выполняет, то все остальное он может делать по своему усмотрению.

Это сообщение отредактировал(а) Fantasist - 11.3.2005, 23:04


--------------------
Волны гасят ветер...
PM MAIL   Вверх
Fantasist
Дата 11.3.2005, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: 4
Всего: 41



Или еще лучше, возьмем два выражения:

Код

c = 1+2*a*b - 36 / (a=(b+2));

и
Код

c = (1+(2*(a*b))) - 36 / (a=(b+2));


Теперь во втором случае "самые вложенные скобки" - это a*b. Значит по твоему утверждению эти два выражения должны давать разные результаты. Давай скомпилируй и убедись.



Добавлено @ 23:06
Цитата(val @ 11.3.2005, 07:25)
Алгоритм разбора обратной польской записи тому пример...


Никакой алгоритм разборе не стандартизирован для использования, а потому использовать компилятор может что хочет.




--------------------
Волны гасят ветер...
PM MAIL   Вверх
Fantasist
Дата 15.3.2005, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


Профиль
Группа: Участник Клуба
Сообщений: 1517
Регистрация: 24.3.2002

Репутация: 4
Всего: 41



Ну что, вопросов больше нет? smile

Это сообщение отредактировал(а) Fantasist - 15.3.2005, 18:07


--------------------
Волны гасят ветер...
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0709 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.