Re[5]: a = a++; каков результат?
От: Кодт Россия  
Дата: 07.05.09 11:50
Оценка: +1 :)
Здравствуйте, elcste, Вы писали:

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


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

Например, пишем в EEPROM (флеш-память)
return (x = x0) + (y = y0)
// превращается в
erase(&x); burn(&x, x0);
erase(&y); burn(&y, y0);

return read(x)+read(y); // либо read(x)+y0, либо x0+read(y), либо x0+y0

Если компилятор сочтёт, что удобно сперва сделать erase(&x), erase(&y), а затем burn(&x,x0), burn(&y,y0), то при алиасинге (&x==&y) мы сперва дважды сотрём, а потом дважды прожжём одну ячейку (получив там x0&y0 или x0|y0 в зависимости от технологии).
... << RSDN@Home 1.2.0 alpha 4 rev. 1207>>
Перекуём баги на фичи!
Re[6]: a = a++; каков результат?
От: jazzer Россия Skype: enerjazzer
Дата: 07.05.09 12:17
Оценка:
Здравствуйте, Кодт, Вы писали:

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


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


К>Как это "точек следования не будет"?

К>Автоматически рассосутся все проблемы с external aliasing? Или оптимизатор задушат, как автомобили с Евро-4?

Будет sequencing. Само понятие точек следования изчезнет.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: a = a++; каков результат?
От: BigBoss  
Дата: 08.05.09 23:59
Оценка: 1 (1) +1 -1 :)
Здравствуйте, Erop, Вы писали:

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


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

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

E>Это тут не при чём, так как (если закрыть глаза на то, что так нельзя) первый аргумент -- это ссылка на a, а второй -- число. Так что тут от порядка ничего зависеть не будет. Ну а вызов функции -- это таки точка следования...

E>Но a тут -- стандартный тип, так что никакого operator = тут нет, и точки следования нет и всё такое...

видимо я что-то пропустил, откуда видно, что a -- это стандартный тип? И что это такое вообще "стандартный тип"?
Re[4]: И охота тебе троллить начинать? Лучше праздник праздн
От: Erop Россия  
Дата: 09.05.09 10:26
Оценка: -1
Здравствуйте, BigBoss, Вы писали:

BB>видимо я что-то пропустил, откуда видно, что a -- это стандартный тип? И что это такое вообще "стандартный тип"?

Действительно пропустил...

...однако все популярные компиляторы (MSVC, GCC) увеличивают значение на 1, а IAR выдает предуждение "undefined behavior".


IMHO, из описания проблемы следует, что a -- это переменная какого-то интегрального типа.
Что такое стандартные типы С++ -- разберись, пожалуйста, сам...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: И охота тебе троллить начинать? Лучше праздник праздн
От: Masterkent  
Дата: 09.05.09 11:29
Оценка: +1 -1
Erop wrote:

E>IMHO, из описания проблемы следует, что a -- это переменная какого-то интегрального типа.


Почему именно интегрального? Это касается переменных любого встроенного скалярного типа, для которого определён встроенный оператор ++.

E>Что такое стандартные типы С++ -- разберись, пожалуйста, сам...


std::complex<double> — это, по-твоему, стандартный тип или нет?
Re[6]: И охота тебе троллить начинать? Лучше праздник праздн
От: Erop Россия  
Дата: 09.05.09 12:09
Оценка: -1
Здравствуйте, Masterkent, Вы писали:

M>Почему именно интегрального? Это касается переменных любого встроенного скалярного типа, для которого определён встроенный оператор ++.


потому, что "увеличиться на 1"...

E>>Что такое стандартные типы С++ -- разберись, пожалуйста, сам...

M>std::complex<double> — это, по-твоему, стандартный тип или нет?
Нет, конечно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: И охота тебе троллить начинать? Лучше праздник праздн
От: Masterkent  
Дата: 09.05.09 13:00
Оценка: +1 :)
Erop, wrote:

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


M>>Почему именно интегрального? Это касается переменных любого встроенного скалярного типа, для которого определён встроенный оператор ++.


E>потому, что "увеличиться на 1"...


double x = 0;
x++;

Здесь переменная x тоже увеличится на 1, но double — это не integral type (не путать с built-in type). Для intergal types в стандарте имеется следующее определение:

3.9.1/7

Types bool, char, wchar_t, and the signed and unsigned integer types are collectively called integral types


E>>>Что такое стандартные типы С++ -- разберись, пожалуйста, сам...

M>>std::complex<double> — это, по-твоему, стандартный тип или нет?
E>Нет, конечно...

А вот у авторов стандарта C++, видимо, иное мнение:

18.2.1/4

Non-fundamental standard types, such as complex<T> (26.2.2), shall not have specializations.

Чем ты можешь доказать ошибочность употребления словосочетания "standard types" в этом контексте?
Re: a = a++; каков результат?
От: TimurSPB Интернет  
Дата: 10.05.09 01:41
Оценка:
Морду надо бить за такой код!
Make flame.politics Great Again!
Re[5]: a = a++; каков результат?
От: Masterkent  
Дата: 10.05.09 14:25
Оценка: 14 (2)
Здравствуйте, elcste, Вы писали:

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

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

Буква стандарта много чего не подтверждает. Полагаться на здравый смысл всё равно приходится.

std::string f()
{
    {
        std::string s = "text";
        return s;
    }
}

Попробуй-ка найти в стандарте подтверждение тому, что выход управления из scope с объявлением s и сопутствующее ему уничтожение объекта s не может произойти до того, как будет произведена попытка скопировать значение s во временный объект, создаваемый в контексте возврата.

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


Абстрактную машину и реализацию следует рассматривать отдельно. Понятие точек следования служит только в целях формализации работы абстрактной машины. Эмулируя одно из возможных наблюдаемых поведений абстрактной машины, реализация не обязана копировать или эмулировать структуру самой абстрактной машины и тем более подчиняться правилам, сформулированным в отношении точек следования (1.9). Для абстрактной машины присваивание определяется следующим образом (5.17/2):

In simple assignment (=), the value of the expression replaces that of the object referred to by the left operand.

Очевидно, такая замена значения не может состояться до того, как будет получен объект, являющийся результатом вычисления правого операнда (нет возвращаемого функцией объекта — нет и значения выражения). Каких-то дополнительных действий, кроме осуществления данной замены, стандарт в отношении абстрактной машины, насколько я знаю, не предусматривает. Таким образом, мы получаем, что на абстрактной машине значение правого операнда формируется после точки следования, которая отделяет дальнейшее присваивание от предшествующего инкремента.

При ином раскладе вычисление подобного выражения может прекратиться до присваивания:

int g(int x);

void f(int &i)
{
    i = g(i++); // may throw
}

Если функция g сгенерирует исключение, то результирующий объект для выражения g(i++) попросту не будет создан, а потому не будет и значения, которым можно было бы заменить значение левого операнда. Разрешения каким-либо образом портить i в таком случае я в стандарте не встречал.

Каким образом реализация будет эмулировать одно из допустимых observable behavior абстрактной машины — это уже проблемы реализации. В случае

#include <iostream>

int foo (int x) { return x; }

int main()
{
    int i = 1;
    i = foo(i++);
    std::cout << i << std::endl;
}

вывод должен быть строго "1".
Re[6]: a = a++; каков результат?
От: vadimcher  
Дата: 10.05.09 19:36
Оценка:
Здравствуйте, Masterkent, Вы писали:

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


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

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

M>Буква стандарта много чего не подтверждает. Полагаться на здравый смысл всё равно приходится.


M>
std::string f()
M>{
M>    {
M>        std::string s = "text";
M>        return s;
M>    }
M>}

M>Попробуй-ка найти в стандарте подтверждение тому, что выход управления из scope с объявлением s и сопутствующее ему уничтожение объекта s не может произойти до того, как будет произведена попытка скопировать значение s во временный объект, создаваемый в контексте возврата.

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


M>Абстрактную машину и реализацию следует рассматривать отдельно. Понятие точек следования служит только в целях формализации работы абстрактной машины. Эмулируя одно из возможных наблюдаемых поведений абстрактной машины, реализация не обязана копировать или эмулировать структуру самой абстрактной машины и тем более подчиняться правилам, сформулированным в отношении точек следования (1.9). Для абстрактной машины присваивание определяется следующим образом (5.17/2):

M>

In simple assignment (=), the value of the expression replaces that of the object referred to by the left operand.

M>Очевидно, такая замена значения не может состояться до того, как будет получен объект, являющийся результатом вычисления правого операнда (нет возвращаемого функцией объекта — нет и значения выражения). Каких-то дополнительных действий, кроме осуществления данной замены, стандарт в отношении абстрактной машины, насколько я знаю, не предусматривает. Таким образом, мы получаем, что на абстрактной машине значение правого операнда формируется после точки следования, которая отделяет дальнейшее присваивание от предшествующего инкремента.

M>При ином раскладе вычисление подобного выражения может прекратиться до присваивания:


M>
int g(int x);

M>void f(int &i)
M>{
M>    i = g(i++); // may throw
M>}

M>Если функция g сгенерирует исключение, то результирующий объект для выражения g(i++) попросту не будет создан, а потому не будет и значения, которым можно было бы заменить значение левого операнда. Разрешения каким-либо образом портить i в таком случае я в стандарте не встречал.

M>Каким образом реализация будет эмулировать одно из допустимых observable behavior абстрактной машины — это уже проблемы реализации. В случае


M>
#include <iostream>

M>int foo (int x) { return x; }

M>int main()
M>{
M>    int i = 1;
M>    i = foo(i++);
M>    std::cout << i << std::endl;
M>}

M>вывод должен быть строго "1".

Да, мне тоже так казалось...

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

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

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

В любом случае присваивание не может быть осуществлено до входа в функцию, т.к. по стандарту сначала вычисляется выражение справа, а осуществление инкремента должно быть до входа. И проблема здесь в том, что при оптимизации тело функции подставляется и второе требование отпадает...

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

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

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

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

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


Это все конечно здорово, но не очень понятно, как это связано в данном случае с проблемой. Ясно, что такое "протирание" будет после использования данной ячейки, а иначе компилятор и такое i=i может во что угодно скомпилировать.

А вот зайца кому, зайца-выбегайца?!
Re[6]: a = a++; каков результат?
От: Masterkent  
Дата: 10.05.09 21:02
Оценка:
Здравствуйте, vadimcher, Вы писали:

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


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

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

V>В любом случае присваивание не может быть осуществлено до входа в функцию


Целиком не может — потому что до входа в функцию значение, которое нужно присвоить, ещё не существует. Произвести часть side-эффектов, относящихся к присваиванию, до точки следования и часть после абстрактная машина также не может — ввиду 1.9/7 ("At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place"). Таким образом, присваивание целиком попадает за точку следования на входе функции.

V>И проблема здесь в том, что при оптимизации тело функции подставляется и второе требование отпадает...


Эта оптимизация относится к реализации, а не абстрактной машине. Если в результате такой оптимизации функция вывода выдаёт нам результат, который не может получиться на абстрактной машине, то это не что иное, как нарушение стандарта.
Re[7]: a = a++; каков результат?
От: vadimcher  
Дата: 10.05.09 23:13
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Эта оптимизация относится к реализации, а не абстрактной машине. Если в результате такой оптимизации функция вывода выдаёт нам результат, который не может получиться на абстрактной машине, то это не что иное, как нарушение стандарта.


Вот, так именно в этом и мой вопрос.

А вот зайца кому, зайца-выбегайца?!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.