Re[5]: a = a++; каков результат?
От: Erop Россия  
Дата: 30.04.09 08:17
Оценка:
Здравствуйте, igna, Вы писали:

I>Это не undefined behavior, это unspecified behavior. И никаких "format D:", у компилятора есть выбор из двух возможностей, сначала выполнить присваивание, затем постинкрементирование или наоборот.


Или как-то несинхронизированно обратиться к памяти и обрушить какую-нибудь экзотическую платформу...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: a = a++; каков результат?
От: igna Россия  
Дата: 30.04.09 08:38
Оценка:
Здравствуйте, Erop, Вы писали:

E>Или как-то несинхронизированно обратиться к памяти и обрушить какую-нибудь экзотическую платформу...


Можно подробнее?
Re[2]: a = a++; каков результат?
От: neFormal Россия  
Дата: 04.05.09 19:04
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

A>>
A>>a = a++;
A>>

АТ>Результат — никакой. Undefined behavior. Никаких правил, по которым, "значение a не должно измениться" нет.

а если ?.
return a++;

тоже UD?.
...coding for chaos...
Re[3]: a = a++; каков результат?
От: Vlad_SP  
Дата: 04.05.09 20:00
Оценка:
Здравствуйте, neFormal, Вы писали:

F>а если ?.

F>
F>return a++;
F>

F>тоже UD?.

Нет, конечно. Однако, в большинстве случаев такой код лишен всякого здравого смысла. Если же ожидаются side effects от a++, то проблемы уже не в коде, а в архитектуре....
Re[4]: a = a++; каков результат?
От: neFormal Россия  
Дата: 04.05.09 20:04
Оценка:
Здравствуйте, Vlad_SP, Вы писали:

F>>а если ?.

F>>
F>>return a++;
F>>

F>>тоже UD?.
V_S>Нет, конечно. Однако, в большинстве случаев такой код лишен всякого здравого смысла. Если же ожидаются side effects от a++, то проблемы уже не в коде, а в архитектуре....

конечно, ожидаются side effects.. например, этот a — это какой-нибудь итератор, который зачем-то хранится..
вопрос был задан только в целях самообразования..
...coding for chaos...
Re[7]: a = a++; каков результат?
От: Erop Россия  
Дата: 04.05.09 23:55
Оценка: 2 (1) +1
Здравствуйте, igna, Вы писали:

I>Можно подробнее?

А что подробнее. Оба побочных эффекта могут работать РЕАЛЬНО параллельно, и это может быть авостом, выполняемым на железном уровне...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: a = a++; каков результат?
От: Erop Россия  
Дата: 04.05.09 23:56
Оценка:
Здравствуйте, Vlad_SP, Вы писали:

V_S>Нет, конечно. Однако, в большинстве случаев такой код лишен всякого здравого смысла. Если же ожидаются side effects от a++, то проблемы уже не в коде, а в архитектуре....


Почему? Например, a может быть полем класса, из метода которого return...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: a = a++; каков результат?
От: Андрей Тарасевич Беларусь  
Дата: 05.05.09 06:23
Оценка:
Здравствуйте, neFormal, Вы писали:

A>>>
A>>>a = a++;
A>>>

АТ>>Результат — никакой. Undefined behavior. Никаких правил, по которым, "значение a не должно измениться" нет.

F>а если ?.

F>
F>return a++;
F>

F>тоже UD?.

Нет. Откуда?

Осмысленность такого кода зависит от того, где определено 'a', но это уже другой вопрос.
Best regards,
Андрей Тарасевич
Re[4]: a = a++; каков результат?
От: neFormal Россия  
Дата: 05.05.09 06:36
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

F>>а если ?.

F>>
F>>return a++;
F>>

F>>тоже UB?.
АТ>Нет. Откуда?
АТ>Осмысленность такого кода зависит от того, где определено 'a', но это уже другой вопрос.

например, это a — это мембер класса, а return делается в методе
a_type Get(){return a++;}

т.е. после return-a что то ещё может быть сделано?.
...coding for chaos...
Re[5]: a = a++; каков результат?
От: Андрей Тарасевич Беларусь  
Дата: 05.05.09 07:44
Оценка: 8 (1)
Здравствуйте, neFormal, Вы писали:

F>Здравствуйте, Андрей Тарасевич, Вы писали:


F>>>а если ?.

F>>>
F>>>return a++;
F>>>

F>>>тоже UB?.
АТ>>Нет. Откуда?
АТ>>Осмысленность такого кода зависит от того, где определено 'a', но это уже другой вопрос.

F>например, это a — это мембер класса, а return делается в методе

F>
F>a_type Get(){return a++;}
F>

F>т.е. после return-a что то ещё может быть сделано?.

А почему нет? На этом return-е программа же, надеюсь, не заканичает свое существование? Если нет, то "после return-a" еще может быть (и будет) много чего сделано. В частности, на выходе из функции стоит точка следования, значит значение 'a' увеличится еще до выхода из функции.
Best regards,
Андрей Тарасевич
Re[2]: a = a++; каков результат?
От: vadimcher  
Дата: 06.05.09 16:30
Оценка:
Здравствуйте, vadimcher, Вы писали:

V>Здравствуйте, ajanov, Вы писали:


A>>a = a++;

A>>Так вот вопрос: какой должен быть результат?

V>Это еще не самое страшное! Вот код:

V>#include <iostream>
V>using namespace std;

V>int foo (int a) { return a; }

V>void main(void) {
V>    int i = 1;
V>    i = foo ( i++ );
V>    cout << i << '\n';
V>}

V>Ответ должен быть 1? Выводит "1", если компилить в режиме "Debug", и "2" -- в режиме "Release".

А вот мне самому интересно стало. Ведь, по идее, по стандарту, данная программа ОБЯЗАНА выдать 1, т.к. я специально вставляю вызов функции, чтобы "подвести итоги" перед присваиванием. Оптимизатор же в режиме Release делает функцию насильственно inline, подставляет, вызов функции как таковой пропадает, и получается undefined, которая в случае моего компилятора выдает 2, хотя мог бы выдать и 5. Как такое поведение оптимизатора регламентируется формально, есть ли тому правила/ограничения?

А вот зайца кому, зайца-выбегайца?!
Re[3]: a = a++; каков результат?
От: Erop Россия  
Дата: 06.05.09 16:32
Оценка:
Здравствуйте, vadimcher, Вы писали:

V>А вот мне самому интересно стало. Ведь, по идее, по стандарту, данная программа ОБЯЗАНА выдать 1, т.к. я специально вставляю вызов функции, чтобы "подвести итоги" перед присваиванием. Оптимизатор же в режиме Release делает функцию насильственно inline, подставляет, вызов функции как таковой пропадает, и получается undefined, которая в случае моего компилятора выдает 2, хотя мог бы выдать и 5. Как такое поведение оптимизатора регламентируется формально, есть ли тому правила/ограничения?


Возможно у тебя сотит опция, которая говорит, что не бывает двух ссылок на один объект (external aliases называется, что-ли, короче опция оптимизации a)
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: a = a++; каков результат?
От: vadimcher  
Дата: 06.05.09 16:40
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, vadimcher, Вы писали:


V>>А вот мне самому интересно стало. Ведь, по идее, по стандарту, данная программа ОБЯЗАНА выдать 1, т.к. я специально вставляю вызов функции, чтобы "подвести итоги" перед присваиванием. Оптимизатор же в режиме Release делает функцию насильственно inline, подставляет, вызов функции как таковой пропадает, и получается undefined, которая в случае моего компилятора выдает 2, хотя мог бы выдать и 5. Как такое поведение оптимизатора регламентируется формально, есть ли тому правила/ограничения?


E>Возможно у тебя сотит опция, которая говорит, что не бывает двух ссылок на один объект (external aliases называется, что-ли, короче опция оптимизации a)


А что это за опция, и как она влияет в данном случае?

P.S. Сейчас посмотрю, что за зверь.

А вот зайца кому, зайца-выбегайца?!
Re[5]: a = a++; каков результат?
От: Erop Россия  
Дата: 06.05.09 18:30
Оценка:
Здравствуйте, vadimcher, Вы писали:

V>А что это за опция, и как она влияет в данном случае?

V>P.S. Сейчас посмотрю, что за зверь.

Ну оптимизатор считает, что каждая ссылка ссылается на уникальный объект. Ну типа функция
 int f( int& a, int& b ) { return ++a, ++b; }
может компилироваться как
int f( int& a, int& b )
{ 
    int res = ++b;
    ++a;
    return res;
}
не смотря на то, что при вызове
int i = 1;
f( i, i );
будет упс...

Да, у gcc, на каком-то из уровней оптимизации по умолчанию это включено...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: a = a++; каков результат?
От: BigBoss  
Дата: 06.05.09 19:31
Оценка:
Здравствуйте, ajanov, Вы писали:

A>Все доброго сремени суток!


A>Сегодня у новичка увидел в коде:



A>
A>a = a++;
A>



A>Так вот вопрос: какой должен быть результат? По правилам C++ значение a не должно измениться, однако все популярные компиляторы (MSVC, GCC) увеличивают значение на 1, а IAR выдает предуждение "undefined behavior".


operator= (a, a++);
А где в стандарте С++ описан порядок вычисления аргументов???
Re[2]: a = a++; каков результат?
От: Erop Россия  
Дата: 06.05.09 21:32
Оценка:
Здравствуйте, BigBoss, Вы писали:

BB>operator= (a, a++);

BB>А где в стандарте С++ описан порядок вычисления аргументов???

Это тут не при чём, так как (если закрыть глаза на то, что так нельзя) первый аргумент -- это ссылка на a, а второй -- число. Так что тут от порядка ничего зависеть не будет. Ну а вызов функции -- это таки точка следования...
Но a тут -- стандартный тип, так что никакого operator = тут нет, и точки следования нет и всё такое...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: a = a++; каков результат?
От: vadimcher  
Дата: 07.05.09 03:24
Оценка:
Здравствуйте, vadimcher, Вы писали:

V>
V>>#include <iostream>
V>>using namespace std;

V>>int foo (int a) { return a; }

V>>void main(void) {
V>>    int i = 1;
V>>    i = foo ( i++ );
V>>    cout << i << '\n';
V>>}
V>

V>>Ответ должен быть 1? Выводит "1", если компилить в режиме "Debug", и "2" -- в режиме "Release".

V>А вот мне самому интересно стало. Ведь, по идее, по стандарту, данная программа ОБЯЗАНА выдать 1, т.к. я специально вставляю вызов функции, чтобы "подвести итоги" перед присваиванием. Оптимизатор же в режиме Release делает функцию насильственно inline, подставляет, вызов функции как таковой пропадает, и получается undefined, которая в случае моего компилятора выдает 2, хотя мог бы выдать и 5. Как такое поведение оптимизатора регламентируется формально, есть ли тому правила/ограничения?


Хорошо, поясню свой вопрос. Есть код:
i=1; i = i++;

Некто ожидает, что порядок выполнения следующий:
1) i=1;
2) i++; возвращает 1 и увеличивает i на 1, т.е. i=2;
3) i=1;
Стандарт на это говорит, что порядок вычислений следующий:
1) i=1: возвращает 1, побочное действие записать 1 в i;
2) записывает 1 в i;
3) i++ возвращает 1, побочное действие: увеличить i на 1;
4) i=i++ возвращает 1, побочное действие: записать 1 в i;
5) выполнение всех побочных действий в любом порядке.

Хорошо, стандарт есть стандарт. В соответствии со стандартом, чтобы первое побочное выполнилось до второго (строго в этом порядке) нам надо явно указать компилятору, чтобы тот перед присвоением не забыл увеличить i, а не наоборот. Для этого перед присвоением вызываем функцию, которая возвращает результат, равный значению на входе:
i = 1; i = foo ( i++ );
В соответствии со стандартом, теперь:
1) i=1: возвращает 1, побочное действие записать 1 в i;
2) записывает 1 в i;
3) i++ возвращает 1, побочное действие: увеличить i на 1;
4) 1 передается как параметр функции, перед этим выполняются все побочные эффекты: i увеличивается на 1, т.е. i=2;
5) foo() возвращает 1;
6) i=foo() возвращает 1, побочное действие: записать 1 в i;
7) выполнение всех побочных действий: i=1.

Теперь, оптимизатор. Оптимизатор, по своей сути, должен оптимизировать, чтобы код выполнялся быстрее или требовал меньше памяти, но логика программы сохранялась. Т.е. в данном случае от оптимизатора ожидается следующее:
1) i=1: возвращает 1, побочное действие записать 1 в i;
2) записывает 1 в i;
3) i++ возвращает 1, побочное действие: увеличить i на 1;
4) выполняются все побочные эффекты: i увеличивается на 1, т.е. i=2;
5) i=1 возвращает 1, побочное действие: записать 1 в i;
6) выполнение всех побочных действий: i=1.

Т.е. функция явно не вызывается, а результат ее работы подставляется. Что же делает оптимизатор? Он не просто оптимизирует выполнение кода, а он приводит выражение обратно к i=i++, а далее компилирует так, будто это и есть то, что написано в коде, при этом нарушая логику работы, когда ему явно был указан порядок выполнения увеличения i и присвоения значения в i (в соответствии со стандартом). Короче, оптимизатор оптимизирует код так, будто там есть undefined, когда его там и в помине нет.

А вот зайца кому, зайца-выбегайца?!
Re[4]: a = a++; каков результат?
От: Кодт Россия  
Дата: 07.05.09 09:54
Оценка:
Здравствуйте, vadimcher, Вы писали:

VV>Стандарт на это говорит, что порядок вычислений следующий:

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

Рассмотрим выражение a = b++.
До вычисления (a,b) принимают значения (a0,b0).
После вычисления (a,b) = (b0,b0+1).

Если &a == &b, то вопрос: чему же будет равна эта переменная? Да чему попало!
Это уже, как минимум, неспецифицированное поведение.

Теперь почему у компилятора развязаны руки: фокус в том, что получить пару чисел (b0,b0+1) можно разными способами.
a = b, b = b+1
b = b+1, a = b-1
c = b, b = b+1, a = c
и т.п.
И это в том случае, если у нас строго скалярная архитектура.
А если векторная или суперскалярная, то компилятор может сформировать операцию групповой записи
(&a, &b) <- (b, b+1)
Раз нет точек следования, то и барьеров памяти (дополнительных тормозов) тоже нет. Но при групповой записи в одну ячейку может случиться страшное.
... << RSDN@Home 1.2.0 alpha 4 rev. 1207>>
Перекуём баги на фичи!
Re[4]: a = a++; каков результат?
От: elcste  
Дата: 07.05.09 10:39
Оценка:
Здравствуйте, vadimcher, Вы писали:

V>>А вот мне самому интересно стало. Ведь, по идее, по стандарту, данная программа ОБЯЗАНА выдать 1, т.к. я специально вставляю вызов функции, чтобы "подвести итоги" перед присваиванием. Оптимизатор же в режиме Release делает функцию насильственно inline, подставляет, вызов функции как таковой пропадает, и получается undefined, которая в случае моего компилятора выдает 2, хотя мог бы выдать и 5. Как такое поведение оптимизатора регламентируется формально, есть ли тому правила/ограничения?


Когда-то давно это здесь уже обсуждали. Консенсус, как мне помнится, так и не был найден. На мой взгляд, поведение MSVC вполне допускается действующим стандартом.

V>Хорошо, поясню свой вопрос. Есть код:
i=1; i = i++;

V>Стандарт на это говорит, что порядок вычислений следующий:

Собственно, стандарт говорит, что "the behavior is undefined". Дальнейшие рассуждения о порядке вычислений не имеют смысла.

i = 1; i = foo ( i++ );

Тут, по моему мнению, ситуация аналогичная. С формальной точки зрения, это все та же модификация скалярного объекта между двумя соседними точками следования. Относительно побочного эффекта постинкремента мы знаем, что он должен выполниться до точки следования перед входом в функцию. Но для присваивания ограничение только одно: до конца полного выражения. И хотя здравый смысл подсказывает, что это может произойти только после выхода из функции, буква стандарта никак это не подтверждает.

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


P.S. С одной стороны, все это теперь не имеет значения, ибо точек следования больше не будет. С другой стороны, как я понимаю, новый стандарт не выйдет и в этом году...
Re[5]: a = a++; каков результат?
От: Кодт Россия  
Дата: 07.05.09 11:37
Оценка: +1
Здравствуйте, elcste, Вы писали:

E>P.S. С одной стороны, все это теперь не имеет значения, ибо точек следования больше не будет. С другой стороны, как я понимаю, новый стандарт не выйдет и в этом году...


Как это "точек следования не будет"?
Автоматически рассосутся все проблемы с external aliasing? Или оптимизатор задушат, как автомобили с Евро-4?
... << RSDN@Home 1.2.0 alpha 4 rev. 1207>>
Перекуём баги на фичи!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.