Сколько будет (a++ + a++)?

 
1 2 3 4 5 6
+
-
edit
 

trainer

втянувшийся

Balancer:
В общем, i = i++; тоже недопустимая конструкция
 
Конструкция допустимая. Результат не определен - скалярный объект меняется в выражении более одного раза. Пост-инкремент и присвоение.
Во имя Ctrl, Alt и святаго Del. Enter!
 
+
-
edit
 

Balancer

администратор
★★★★★
trainer, 06.07.2004 14:28:30 :
Результат не определен - скалярный объект меняется в выражении более одного раза.
 


i = (i=5) + (i+1) - допустимо или нет? :D
 
RU Филич #06.07.2004 14:48
+
-
edit
 

Филич

втянувшийся

Да их, знаешь, не из-за несоответствия синтаксиса ++ пишут
 

я ж утрировал :D
могет что то в идеологии хотели развить/изменить. задачи опять таки другие.


Всё же, по логике:
i++ возвращает старое значение i, так?
Это значение присваивается пременной i.
 

точно так, но только наоборот: сначала присваиваем, а потом изменяем.
существуют только два типа кораблей: подводные лодки и их цели
 
+
-
edit
 

Balancer

администратор
★★★★★
Филич, 06.07.2004 14:48:24 :
Всё же, по логике:
i++ возвращает старое значение i, так?
Это значение присваивается пременной i.
 

точно так, но только наоборот: сначала присваиваем, а потом изменяем.
 


Нелогично! :)
i = (i++) - сперва все действия в скобках обязаны выполняться по всем канонам :)
 
RU Squirrelcage #06.07.2004 16:48
+
-
edit
 

Squirrelcage

новичок
Пардон за вмешательство :) В поддержку Филича:

Для С/С++, эквивалентом выражения
a = a++ + a++;
будет последовательность
a = a + a; a++; a++;

Неопределенностей тут нет, программиста написавшего такую муть увольнять не обязательно :)

Для проверки можно посмотреть листинг (в смысле, ассемблерный код)следующего фрагмента с включенной по максимуму оптимизацией:
volatile int a = 5;
a = a++ + a++;

>Так что или i = ++i не определено, что, по меньшей мере глупо, или i = ++i +1 тоже определено, но тогда в стандарте - явный бред.

В чем именно бред? Тут все в порядке
i = ++i + 1; эквивалентно i = i + 2;
i = ++i; эквивалентно i = i + 1;
 
+
-
edit
 

Balancer

администратор
★★★★★
Squirrelcage, 06.07.2004 16:48:42 :
Неопределенностей тут нет
 


Читай внимательнее написанное ранее :)

"i = ++i + 1; // the behavior is unspecified" - это из стандарта, однако.

А неопределённость именно в двусмысленном толковании Кернигана и Ричи.
Почему-то разработчики протестированных компиляторов Си++ пошли по твоему объяснению, разработчики других языков - по более буквальной трактовке :) Там ++ выполняется сразу после извлечения значения из переменной, что допускает меньше отклонений в определении.

А в Си++, как показывают, вышеприведённые примеры, operator++ для классов пользователя и ++, встроенный в систему работают по-разному. Что, сам понимаешь, нелогично.
 
RU Филич #06.07.2004 17:16
+
-
edit
 

Филич

втянувшийся

кстати, для i = ++i + 1 ; генерится нормальный код. сначала инкремент, потом прибавление единицы.

А в Си++, как показывают, вышеприведённые примеры, operator++ для классов пользователя и ++, встроенный в систему работают по-разному. Что, сам понимаешь, нелогично.
 

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

по моему у тех, кто сразу применяет ++ и тех, кто делает это после окончания выражения, разные понимания sequence point. хотя все как будто прозрачно:
Accessing an object designated by a volatile lvalue (basic.lval), modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment. Evaluation of an expression might produce side effects. 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.
 
существуют только два типа кораблей: подводные лодки и их цели
 
+
-
edit
 

Balancer

администратор
★★★★★
Филич, 06.07.2004 17:16:45 :
более, чем логично. operator ++() и просто ++ - две большие разницы.
 


абсолютно нелогично :)
 
RU Филич #06.07.2004 17:19
+
-
edit
 

Филич

втянувшийся

кстати говоря. по-моему как раз "сишная" трактовка более жизненна и логична. потому что в выражении мы используем определенное значение переменной. а лишь потом изменяем его.
существуют только два типа кораблей: подводные лодки и их цели
 
RU Филич #06.07.2004 17:20
+
-
edit
 

Филич

втянувшийся

ты чего???
The operator keyword declares a function specifying what operator-symbol means when applied to instances of a class. This gives the operator more than one meaning, or "overloads" it. The compiler distinguishes between the different meanings of an operator by examining the types of its operands.

You can redefine the function of most built-in operators globally or on a class-by-class basis. Overloaded operators are implemented as functions.
 

MSDN
существуют только два типа кораблей: подводные лодки и их цели
 
+
-
edit
 

Balancer

администратор
★★★★★
Филич, 06.07.2004 17:20:35 :
ты чего???
 


Потому что в Си++ приоритеты и порядок операторов не перегружаются!
Поэтому, понятно, что выполнять они могут и что-то совсем другое, но вот порядок вызова должен быть одинаков что для встроенных, что для перегруженных функций. Иначе - бред.
 
RU Филич #06.07.2004 17:48
+
-
edit
 

Филич

втянувшийся

operator это функция со всеми вытекающими. а +, - , *, / это просто операторы языка.
наверное мы спорим уже не о том. по мне так все понятно и логично. у тебя другое видение - соответсвенно разнимся в понимании :)

вот, пример более правильный с постфиксными и префиксными перегруженными операторами
code text
  1. class Integer
  2. {
  3. public:
  4.     Integer(int Num) : m_iNum(Num) {}
  5.     operator int() { return m_iNum; }
  6.  
  7.     Integer operator+(const Integer& I) { return m_iNum + I.m_iNum; }
  8.     Integer operator++(int i) { return m_iNum++; }
  9.     Integer& operator++() { ++m_iNum; return *this}
  10.     Integer& operator = (const Integer& I) { m_iNum = I.m_iNum; return *this; }
  11. private:
  12.     int m_iNum;
  13. };

кстати, как думаешь, какой результат должно иметь выражение i = i++ + ++i; ?
существуют только два типа кораблей: подводные лодки и их цели
 
Это сообщение редактировалось 06.07.2004 в 17:59
+
-
edit
 

Balancer

администратор
★★★★★
Филич, 06.07.2004 17:48:48 :
кстати, как думаешь, какой результат должно иметь выражение i = i++ + ++i; ?
 


Если по логике - то
i = i + i + 2

Думаю, что в Си++ тоже будет 12 :D
Но по другой логике работы.

Прверяю. i=5;
Perl -> 12
PHP -> 12
C# -> 12

Оп-па! А вот тут я промахнулся.

C++ (VC7) -> 13!

Объясни результат :D
По твоей логике должно быть 5 + 6 и потом увеличение i на 1 от i++ -> 12.

Я не прав?

>у тебя другое видение - соответсвенно разнимся в понимании

Оно не только у меня "другое", но и у большинства других разработчиков компиляторов с такой нотацией. Так у кого оно тогда "другое"? :)
 
+
-
edit
 

Balancer

администратор
★★★★★
Balancer, 06.07.2004 17:58:06 :
Оп-па! А вот тут я промахнулся.
C++ (VC7) -> 13!
 


Понятно. ++i срабатывает тоже не перед извлечением данных, а перед обработкой всего выражения.

В общем, основная масса разработчиков с этим не согласна, в самом стандарте Си++ такие операции не определены, так с чего ты считаешь, что конкретные реализации компиляторов Си++ - более правильные? :D
 
RU Филич #06.07.2004 18:05
+
-
edit
 

Филич

втянувшийся

объясняю:
сначала выполянем ++i
i становится равным 6
далее складываем i + i
получаем 12
потом i++
результат 13 :)

По твоей логике должно быть 5 + 6 и потом увеличение i на 1 от i++ -> 12.
 

вот она где собака порылась! не 5 + 6, а именно 6 + 6. мы же в префиксном операторе поменяли значение i. посмотри на асемблерный код:
code text
  1. [b]i = i++ + ++i;[/b]
  2. [b]++i[/b]
  3. 00411A6F  mov         eax,dword ptr [i]
  4. 00411A72  add         eax,1
  5. [b]i + i[/b]
  6. 00411A75  mov         dword ptr [i],eax
  7. 00411A78  mov         ecx,dword ptr [i]
  8. 00411A7B  add         ecx,dword ptr [i]
  9. [b]i = [/b]
  10. 00411A7E  mov         dword ptr [i],ecx
  11. [b]i++[/b]
  12. 00411A81  mov         edx,dword ptr [i]
  13. 00411A84  add         edx,1
  14. 00411A87  mov         dword ptr [i],edx

(вставки болдом - мои)
существуют только два типа кораблей: подводные лодки и их цели
 
RU Филич #06.07.2004 18:06
+
-
edit
 

Филич

втянувшийся

ой..что то болд не получился :)
существуют только два типа кораблей: подводные лодки и их цели
 
RU Squirrelcage #06.07.2004 18:20
+
-
edit
 

Squirrelcage

новичок
>Читай внимательнее написанное ранее
>i = ++i + 1; // the behavior is unspecified" - это из стандарта, однако.

Упс. Как раз цитату из стандарта прочитал мимо.

Да, забавно.. Даже нет смысла обсуждать, что выдаст С++ при вычислении a = a++ + a++ и тому подобных выражений, т.к. прямо указано, что результат неопределен.

Интересно, почему же тогда компилятор не выдает предупреждений даже на максимальном warning level? (проверял в VC++ 6).

>А неопределённость именно в двусмысленном толковании Кернигана и Ричи.

Разработчики компиляторов C почему-то толковали это дело одинаково (обратных примеров, и почему так, не знаю).

>А в Си++, как показывают, вышеприведённые примеры, operator++ для классов пользователя и ++, встроенный в систему работают по-разному. Что, сам понимаешь, нелогично.

Результат для примера с перегрузкой постфиксного инкремента вполне предсказуем и объясним, если помнить, что перегруженные операторы - на самом деле функции с кривыми именами :)

Нелогично - да. Сдается мне, что это и объясняет сказанное в стандарте. Никакого другого разумного объяснения в голову не приходит. Если ограничиться только встроенными типами, ИМХО результат вышеупомянутых операций определен однозначно.
 
Это сообщение редактировалось 06.07.2004 в 18:28

Rada

опытный

а в случае с class Integer - сам понимаешь ни о каких операторах речи не идет
 
А нет разницы между оператором и функцией (кроме быстрого вычисления && и || по типу "короткого замыкания"). Также, перегружая операторы ты не меняешь их приоритеты и ассоциативность.
С себя можно начать когда все остальное будет в порядке.  

Rada

опытный

Сдается мне, что это и объясняет сказанное в стандарте.
 
То сть, в стандарте сказано, что GCC даёт 12, а VC++ даёт 10? :rolleyes:
С себя можно начать когда все остальное будет в порядке.  
+
-
edit
 

Balancer

администратор
★★★★★
Rada, 06.07.2004 19:04:25 :
Также, перегружая операторы ты не меняешь их приоритеты и ассоциативность.
 


Собственно, об этом я и говорю, когда пинаю на неувязку в поведении ++ и operator++ :)

Почему-то ++ работает не так, как ++ в других языках, а вот operator++ - также, как и всюду :D
 
RU Squirrelcage #06.07.2004 19:17
+
-
edit
 

Squirrelcage

новичок
>То есть, в стандарте сказано, что GCC даёт 12, а VC++ даёт 10?

Не понял, где VC++ дает 10?
 

Rada

опытный

Rada, 05.07.2004 20:57:55 :
code text
  1. int main(int argc, char* argv[])
  2. {
  3.         int a = 5;
  4.  
  5.         int b = (a++) + (a++);
  6.  
  7.         return 0;
  8. }
У меня b = 10. VC++ 6.0
 


Тута. VC++ 6.0.
С себя можно начать когда все остальное будет в порядке.  
+
-
edit
 

Balancer

администратор
★★★★★
Кстати, в ту же степь нелогичности. То, как реализован (недостоверный по стандарту) механизм ++ в Си++ компиляторах - это откровенное неявное действие, которое является таким бичем императивных языков. Типа, сперва проходят вычисления, присваивания, а потом - инкремент. Это откровенная неявщина. А вот то, что реализовано в C#/PHP/Perl или в operator++ (и всё руки в Java проверить не доходят) - это всё укладывается в базовое описание и не создаёт никаких скрытых эффектов. Взяли значение, увеличили переменную - всё строго логично в элементарных действиях.
 
+
-
edit
 

Balancer

администратор
★★★★★
Rada, 06.07.2004 19:19:29 :
Тута. VC++ 6.0.
 


Упс, там у Рады ошибка - надо не int b = (a++) + (a++); а int a = (a++) + (a++);
 
+
-
edit
 

Balancer

администратор
★★★★★
вот, сформулировал, наконец, что мне не нравится.

Для меня операция присваивания - это всегда последняя операция в вычислениях. И должна выполняться в последнюю очередь. Потому что иначе - просто вопреки всякой логике :D Сперва вычислили рещультат. Если надо - вычислили чему присвоить. Сохраниили. Так оно и работает во всех случаях, кроме встроенного ++ в Си++. Там же уже после присванивания происходит скрытая операция над числом. По любой логике после
b = f(a)
a = f(a)

a должно быть равно b. В случае всех прочих реализация это так, но в пресловутом встроенном ++ - нет! :)

(b = a++ + a++) !== (a = a++ + a++)

Это, вот хоть тресни, неправильно! :)
 
1 2 3 4 5 6

в начало страницы | новое
 
Поиск
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru