![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| 17dufa |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 324 Регистрация: 2.3.2006 Репутация: 3 Всего: 5 |
Добрый день. Есть красивая подстава на собеседовании: int i = 0; i = i++; чему равно i?
однако, компилятор мелкософта, а по сведениям и какие-то из линуксовых выдают i == 1. вот собственно код
при выходе из main jk = 1, а вот i.val = 0 - как и ожидалось. откуда такая разница для встроенного и пользовательского типа? Это сообщение отредактировал(а) 17dufa - 30.10.2009, 11:49 |
|||
|
||||
| Alek86 |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1299 Регистрация: 30.1.2007 Где: Киев Репутация: 21 Всего: 25 |
оттуда, что поведение не определено (или не специфицированно, не помню точно)
если ты напишешь код, у которого undefined behaviour, компилятор имеет моральное право хоть код для BSOD'а вставлять Это сообщение отредактировал(а) Alek86 - 30.10.2009, 12:04 |
|||
|
||||
| mes |
|
||||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
для удобства в выражении i = i++; заменим i ссылками на нее же :
теперь разобьем по действиям : (условно a и b регистры процессора)
результат зависит от того, какая из закомментированных строк будет использована.. точнее от порядка следования инструкций сохранения значения. как тут поступить решает компилятор, так как в стандарте нет жестких указаний на данный случай. Это сообщение отредактировал(а) mes - 30.10.2009, 13:14 |
||||
|
|||||
| 17dufa |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 324 Регистрация: 2.3.2006 Репутация: 3 Всего: 5 |
Alek86, что конкретно в этом коде выводит нас в чудную область undefined behaviour?
mes, думаю Вы несколько ошиблись в коде (перепутали a и b в последней части)
а разве не определено стандартом, что сначала вычисляется правое выражение, а затем уже выполняется оператор равенства? это ж форменный бардак получается, если side эффекты правого выражения вычисляются после выполнения равенства. |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
спасибо.. подправил..
одно дело вычисление, а другое дело сохранение результатов в переменной, так как процессор делает подобные операции не над ячейками памяти, а над регистрами. Добавлено через 6 минут и 6 секунд Стандарт Вас честно предупреждает о возможности side-эффекта, и это уж на совести программиста создвать бардак или нет |
|||
|
||||
| tilin |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
А почему i не должно быть равно 1? i хранится в памяти. i инкрементируется и сохраняется опять же туда. Соответственно при чтении i читается из памяти и читается именно 1. Асм код от мелкософта:
|
||||
|
|||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
потому что может быть и другая реализация.. Не мелкософтом единным жив программист |
|||
|
||||
| tilin |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 23.9.2008 Репутация: нет Всего: нет |
А при другой реализации i будет храниться в двух разных местах что-ли? Ведь, если хранится в одном месте памяти, то i++ изменяет значение именно этой ячейки и соответственно i == 1 при любом порядке выполнения.
|
|||
|
||||
| 17dufa |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 324 Регистрация: 2.3.2006 Репутация: 3 Всего: 5 |
tilin, ну вот Вы и попались
i=i++ - это единая конструкция. и в оператор = передается значение i до инкрементирования, то есть 0. потом происходит инкремент, i становится 1, потом собственно выполняется оператор = и i снова становится 0;) а приведенный Вами код несколько отличается от того, что я написал в самом начале. так что в идеале i = 0. что и происходит с моим типом ii. там компилятор себе такого не позволяет. mes, ну все, если терь меня такое спросят так и буду грить - undefined behaviour и Вашу красивую схему с регистрами tilin, исправились, так что и я исправлюсь - постфиксный инкремент создает копию объекта, глубоко по идее. так что да, в 2 местах будет хранится. обратите внимание на реализацию operator++(int) в первом посте темы. Это сообщение отредактировал(а) 17dufa - 30.10.2009, 13:43 |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
если пример приведенный выше остался без внимания, то повторю его изменив "Ваш" asm код :
Добавлено через 6 минут позвольте узнать, на что он может обидеться ?! |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
Нет, компилятор имеет право делать присваивание и инкремент в любом порядке, т.к. инкремент постфиксный. Порядок вычисления независимых подвыражений в statement не определен. А результат i++ (т.е. старое значение i) может храниться во временной переменной. -------------------- ... |
|||
|
||||
| 17dufa |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 324 Регистрация: 2.3.2006 Репутация: 3 Всего: 5 |
mes, если предположить, что он умный ровно настолько насколько я был до этого утра и твердо уверен что результат 0, то может обидеться, что я оказался умнее
Earnest, вот где собака порылась. для моего типа это получается ни разу не независимое подвыраженее, и как следствие подобной вариативности нет, а постфиксный инкремент встроенного типа независимое подвыражение со всеми вытекающими. тогда все становится на свои места. |
|||
|
||||
| mes |
|
|||
|
любитель ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 7954 Регистрация: 14.1.2006 Репутация: 144 Всего: 250 |
или про точки следования, вот с википедии : http://en.wikipedia.org/wiki/Sequence_point
тогда зачем бы он стал бы задавать такой вопрос на собеседовании. ?! ну если уж работадатель задает вопросы, ответы на которые не знает, то ничего страшного если и покраснеет Все зависит от оптимизационных способностей компилятора.. Это сообщение отредактировал(а) mes - 30.10.2009, 14:14 |
|||
|
||||
| 17dufa |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 324 Регистрация: 2.3.2006 Репутация: 3 Всего: 5 |
mes, познавательно. и что самое интересное "i=i++;" даже обсуждается отдельно.
Это сообщение отредактировал(а) 17dufa - 30.10.2009, 15:31 |
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |