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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> не понимаю компилятор 
V
    Опции темы
17dufa
Дата 30.10.2009, 11:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Добрый день. Есть красивая подстава на собеседовании: int i = 0; i = i++; чему равно i?
однако, компилятор мелкософта, а по сведениям и какие-то из линуксовых выдают i == 1.
вот собственно код
Код

class ii
{
    int val;
public:
    ii(int j) : val(j){}
    ii & operator = (ii&op)
    {
        this->val = op.val;
        return *this;
    }
    ii operator++(int)
    {
        ii buf = *this;
        this->val++;
        return buf;
    }
};

int main()
{
    int jk = 0;
    jk = jk++;
    ii i = 0;
    i = i++;
    int j = 0;
}

при выходе из main jk = 1, а вот i.val = 0 - как и ожидалось. откуда такая разница для встроенного и пользовательского типа?

Это сообщение отредактировал(а) 17dufa - 30.10.2009, 11:49
PM MAIL   Вверх
Alek86
Дата 30.10.2009, 12:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

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



оттуда, что поведение не определено (или не специфицированно, не помню точно)
если ты напишешь код, у которого undefined behaviour, компилятор имеет моральное право хоть код для BSOD'а вставлять smile

Это сообщение отредактировал(а) Alek86 - 30.10.2009, 12:04


--------------------
user posted image    user posted image
PM MAIL   Вверх
mes
Дата 30.10.2009, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



для удобства в выражении i = i++; заменим i ссылками на нее же :    
Код

int & i1 = i;
int & i2 = i;  
i2 = i1++;


теперь разобьем по действиям :
(условно a и b регистры процессора)
Код

a = i1;
b = a + 1;

// i1 = b; 
i2 = a;    // i = 1;
// i1 = b; // i = 0;

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

Это сообщение отредактировал(а) mes - 30.10.2009, 13:14


--------------------
PM MAIL WWW   Вверх
17dufa
Дата 30.10.2009, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Alek86, что конкретно в этом коде выводит нас в чудную область undefined behaviour?


mes, думаю Вы несколько ошиблись в коде (перепутали a и b в последней части)
Код

a = i1;
b = a + 1;
// i1 = b; 
i2 = a;    // i = 1;
// i1 = b; // i = 0;

а разве не определено стандартом, что сначала вычисляется правое выражение, а затем уже выполняется оператор равенства?
это ж форменный бардак получается, если side эффекты правого выражения вычисляются после выполнения равенства.
PM MAIL   Вверх
mes
Дата 30.10.2009, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(17dufa @  30.10.2009,  11:57 Найти цитируемый пост)
думаю Вы несколько ошиблись в коде 

спасибо.. подправил..

Цитата(17dufa @  30.10.2009,  11:57 Найти цитируемый пост)
а разве не определено стандартом, что сначала вычисляется правое выражение, а затем уже выполняется оператор равенства?

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

Добавлено через 6 минут и 6 секунд
Цитата(17dufa @  30.10.2009,  11:57 Найти цитируемый пост)
это ж форменный бардак получается

Стандарт Вас честно предупреждает о возможности side-эффекта, и это уж на совести программиста создвать бардак или нет 
 smile 



--------------------
PM MAIL WWW   Вверх
tilin
Дата 30.10.2009, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(17dufa @  30.10.2009,  11:47 Найти цитируемый пост)
Есть красивая подстава на собеседовании: int i = 0; i = i++; чему равно i?
однако, компилятор мелкософта, а по сведениям и какие-то из линуксовых выдают i == 1.


А почему i не должно быть равно 1? i хранится в памяти. i инкрементируется и сохраняется опять же туда. Соответственно при чтении i читается из памяти и читается именно 1. Асм код от мелкософта:
Код

    int i = 0; 
004114AE  mov         dword ptr [i],0 
    i = i++;
// i = i
004114B5  mov         eax,dword ptr [i] 
004114B8  mov         dword ptr [i],eax

// i++ 
004114BB  mov         ecx,dword ptr [i] 
004114BE  add         ecx,1 
004114C1  mov         dword ptr [i],ecx

PM MAIL   Вверх
mes
Дата 30.10.2009, 13:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(tilin @  30.10.2009,  12:30 Найти цитируемый пост)
А почему i не должно быть равно 1? 

потому что может быть и другая реализация..

Цитата(tilin @  30.10.2009,  12:30 Найти цитируемый пост)
Асм код от мелкософта:

Не мелкософтом единным жив программист smile



--------------------
PM MAIL WWW   Вверх
tilin
Дата 30.10.2009, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



А при другой реализации i будет храниться в двух разных местах что-ли? Ведь, если хранится в одном месте памяти, то i++ изменяет значение именно этой ячейки и соответственно  i == 1 при любом порядке выполнения.
PM MAIL   Вверх
17dufa
Дата 30.10.2009, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



tilin, ну вот Вы и попалисьsmile
i=i++ - это единая конструкция. и в оператор = передается значение i до инкрементирования, то есть 0. потом происходит инкремент, i становится 1, потом собственно выполняется оператор = и i снова становится 0;) а приведенный Вами код несколько отличается от того, что я написал в самом начале. так что в идеале i = 0. что и происходит с моим типом ii. там компилятор себе такого не позволяет.


mes, ну все, если терь меня такое спросят так и буду грить - undefined behaviour и Вашу красивую схему с регистрами smile главное чтоб работодатель с юмором попался, а то еще обидется.

tilin, исправились, так что и я исправлюсь - постфиксный инкремент создает копию объекта, глубоко по идее. так что да, в 2 местах будет хранится. обратите внимание на реализацию operator++(int) в первом посте темы.

Это сообщение отредактировал(а) 17dufa - 30.10.2009, 13:43
PM MAIL   Вверх
mes
Дата 30.10.2009, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(tilin @  30.10.2009,  12:35 Найти цитируемый пост)
А при другой реализации i будет храниться в двух разных местах что-ли? Ведь, если хранится в одном месте памяти, то i++ изменяет значение именно этой ячейки и соответственно  i == 1 при любом порядке выполнения. 

 
если пример приведенный выше остался без внимания, то повторю его изменив "Ваш" asm код :

Код

  mov         eax,dword ptr [i] 
  mov         ecx,dword ptr [i] 
  add         ecx,1 
  mov         dword ptr [i],ecx
  mov         dword ptr [i],eax

 smile

Добавлено через 6 минут
Цитата(17dufa @  30.10.2009,  12:40 Найти цитируемый пост)
главное чтоб работодатель с юмором попался, а то еще обидется.

позвольте узнать, на что он может обидеться ?!


--------------------
PM MAIL WWW   Вверх
Earnest
Дата 30.10.2009, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



Цитата(17dufa @  30.10.2009,  14:40 Найти цитируемый пост)
i=i++ - это единая конструкция. и в оператор = передается значение i до инкрементирования, то есть 0. потом происходит инкремент

Нет, компилятор имеет право делать присваивание и инкремент в любом порядке, т.к. инкремент постфиксный. Порядок вычисления независимых подвыражений в statement не определен. А результат i++ (т.е. старое значение i) может храниться во временной переменной.



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


Опытный
**


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

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



mes, если предположить, что он умный ровно настолько насколько я был до этого утра и твердо уверен что результат 0, то может обидеться, что я оказался умнее smile 

Earnest, вот где собака порылась. для моего типа это получается ни разу не независимое подвыраженее, и как следствие подобной вариативности нет, а постфиксный инкремент встроенного типа независимое подвыражение со всеми вытекающими. тогда все становится на свои места.
PM MAIL   Вверх
mes
Дата 30.10.2009, 14:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(17dufa @  30.10.2009,  12:40 Найти цитируемый пост)
если терь меня такое спросят так и буду грить .. 

или  про точки следования, вот с википедии :
http://en.wikipedia.org/wiki/Sequence_point
 smile

Цитата(17dufa @  30.10.2009,  13:04 Найти цитируемый пост)
если предположить, что он умный ровно настолько насколько я был до этого утра и твердо уверен что результат 0, то может обидеться, что я оказался умнее smile 

тогда зачем бы он стал бы задавать такой вопрос на собеседовании. ?! ну  если уж работадатель задает вопросы, ответы на которые не знает, то ничего страшного если и покраснеет smile

Цитата(17dufa @  30.10.2009,  13:04 Найти цитируемый пост)
 вот где собака порылась. 

Все зависит от оптимизационных способностей компилятора..


Это сообщение отредактировал(а) mes - 30.10.2009, 14:14


--------------------
PM MAIL WWW   Вверх
17dufa
Дата 30.10.2009, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



mes, познавательно. и что самое интересное "i=i++;" даже обсуждается отдельно. 

Это сообщение отредактировал(а) 17dufa - 30.10.2009, 15:31
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.0579 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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