Форум программистов, компьютерный форум CyberForum.ru

Постфиксный и префиксный декремент - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.79
BloodyWo1f
Сообщений: n/a
26.06.2013, 19:22     Постфиксный и префиксный декремент #1
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
using std::cout;
int main() 
{
int a=5;
 cout << (--a)-- << " "; 
 cout << a << " ";
 cout << (--a)-- << " "; 
 cout << (--a)-- << " "; 
 cout << a << " ";
system("pause"); 
return 0;
}
Помогите пожалуйста. Не могу понять почему сперва выводит 4 но а=3 потом выводит 2 а потом 0 но а=-1. Почему сначала отнимает 1 а потом 2.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ValeryS
Модератор
6377 / 4843 / 442
Регистрация: 14.02.2011
Сообщений: 16,057
26.06.2013, 23:27     Постфиксный и префиксный декремент #21
Цитата Сообщение от Toshkarik Посмотреть сообщение
При вычислении этого выражения переменная изменяется дважды.
и что?
на следующей строчке все в порядке будет
ведь мы здесь не присваиваем
или компилятор выбросит одно уменьшение?

Добавлено через 3 минуты
Цитата Сообщение от Croessmah Посмотреть сообщение
у постфиксного выше
всегда думал наоборот
тогда действительно ерунда получается
Не будем так писать
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Kuzia domovenok
 Аватар для Kuzia domovenok
1883 / 1738 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
26.06.2013, 23:28     Постфиксный и префиксный декремент #22
Цитата Сообщение от Toshkarik Посмотреть сообщение
При вычислении этого выражения переменная изменяется дважды.
И что, что изменяется дважды? Вот ты что-то споришь всё, утверждая:
Цитата Сообщение от Toshkarik Посмотреть сообщение
Результат может быть каким угодно.
А давай начнём с того, что при UB программа генерирует не какое-то рандомное значение -12345, а некую последовательность действий, которая для некоторых компиляторов разная, т.к. стандарт не описывает точное поведение в этих случаях.
Так вот ты утверждаешь, что эту программу возможно интерпретировать каким-то иным образом, кроме
Цитата Сообщение от ValeryS Посмотреть сообщение
идет уменьшение
потом вывод на экран ( в поток) вот она точка следования
и потом еще раз уменьшение
Можно поинтересоваться, какие тут могут быть альтернативные действия?
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
26.06.2013, 23:29     Постфиксный и префиксный декремент #23
@Croessmah, да дело уже даже не в порядке, а в
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.
В данном случае ( --i )-- это и есть expression и в нем не соблюдается value modified at most once, уже и не знаю, что еще добавить, и как еще написать.
razor_ua
10 / 10 / 0
Регистрация: 20.05.2011
Сообщений: 71
26.06.2013, 23:35     Постфиксный и префиксный декремент #24
при
C++
1
cout<< ++i + ++i ;
будет 4,
а значение i=2.
(т.е. сначала выполнятся 2 раза ++, а потом сложатся)

при
C++
1
cout<< i++ + i++;
выведется 0, i = 2;

при
C++
1
cout << ++i + i++;
выведется 2, i =2

делайте простые выводы
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,917
Записей в блоге: 2
Завершенные тесты: 1
26.06.2013, 23:41     Постфиксный и префиксный декремент #25
Цитата Сообщение от razor_ua Посмотреть сообщение
делайте простые выводы
а теперь сделайте так:
C++
1
(i++ - i++)
на разных компиляторах получите разные ответы.
А у Вас получались одинаковые, потому что хоть задом наперед все сделай, все равно будет одинаковый ответ. А вот при разности, ну или при разных подвыражениях будет бо-бо...
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
26.06.2013, 23:52     Постфиксный и префиксный декремент #26
@Kuzia domovenok, я не занимаюсь исследованием компиляторов, мне это не к чему. Возможно, что все существующие компиляторы оценят это выражения так, как описано в теме. Но это ничего не меняет по отношению к стандарту.

И да, это утверждение не верно:
Цитата Сообщение от ValeryS
потом вывод на экран ( в поток) вот она точка следования
и потом еще раз уменьшение
std::cout << ( --i )--; раскрывается компилятором как cout.operator<<(( --i )--);, следовательно оно должно быть вычислено до вызова функции. В момент вызова функции постдекремент уже выполнен, а в функцию передается копия.

@razor_ua, мда, тут все понятно...
razor_ua
10 / 10 / 0
Регистрация: 20.05.2011
Сообщений: 71
26.06.2013, 23:55     Постфиксный и префиксный декремент #27
мда.... при ВЫЧИТАНИИ сначала выполняется ++ 2 раза, пофиг с какой стороны, и выводится результат отнимания..

а при сложении только 1 инкремент...
теперь ночью будут кошмары сниться )))
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,917
Записей в блоге: 2
Завершенные тесты: 1
26.06.2013, 23:57     Постфиксный и префиксный декремент #28
Цитата Сообщение от Toshkarik Посмотреть сообщение
Но это ничего не меняет по отношению к стандарту.
Что же Вы одно предложение выдернули то из стандарта?
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified(53)
Between the previousand next sequence point a scalar object shall have its stored value modified at most once by the evaluation
of an expression. F
и еще сноска внизу:
(53)The precedence of operators is not directly specified, but it can be derived from the syntax.
То бишь никакого UB, если порядок может быть получен из синтаксиса
Kuzia domovenok
 Аватар для Kuzia domovenok
1883 / 1738 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
27.06.2013, 00:00     Постфиксный и префиксный декремент #29
Цитата Сообщение от Toshkarik Посмотреть сообщение
std::cout << ( --i )--; раскрывается компилятором как cout.operator<<(( --i )--);, следовательно оно должно быть вычислено до вызова функции. В момент вызова функции постдекремент уже выполнен, а в функцию передается копия.
Это ты типа доказываешь, что "то утверждение неверно"?
Больше похоже наоборот, на подтверждение слов @Croessmah
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,917
Записей в блоге: 2
Завершенные тесты: 1
27.06.2013, 00:08     Постфиксный и префиксный декремент #30
@Toshkarik, UB происходит в данных случаях от того, что в разных компиляторах дерево строится по разному и все зависит от того, в каком порядке это дерево "обходится", а это зависит от реализации. А значит нет однозначного ответа в каком порядке будут выполнены подвыражения. В случае с (--a)-- скобки влияют на построение дерева таким образом, что выполнить по другому просто не получится
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
27.06.2013, 00:08     Постфиксный и префиксный декремент #31
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
Это ты типа доказываешь, что "то утверждение неверно"?
Это я "типа" говорю, что никакого второго уменьшения после вывода на экран нет, выражение вычисляется один раз до вызова функции.

@Croessmah, я не вставил это в цитату, потому что, если верить сноски, то, как я уже писал, выражение ++++++i неявно оценивается компилятором как ++( ++( ++i )), что является UB, отсюда сделал вывод, что и ( --i )-- является UB.
ValeryS
Модератор
6377 / 4843 / 442
Регистрация: 14.02.2011
Сообщений: 16,057
27.06.2013, 00:11     Постфиксный и префиксный декремент #32
Цитата Сообщение от Toshkarik Посмотреть сообщение
std::cout << ( --i )--; раскрывается компилятором как cout.operator<<(( --i )--);, следовательно оно должно быть вычислено до вызова функции. В момент вызова функции постдекремент уже выполнен, а в функцию передается копия.
нехай так
передается копия
что это меняет
C++
1
2
int i=2;
std::cout << ( --i )--;
т.е на экран выведется 1
а в следующей строчке i==0;
при любых компиляторах
где тут неопределенное поведение?
и мне без разницы выведет он переменную а потом уменьшит или создаст копию уменьшит а потом выведет копию
главное результат предсказуем

ты ведь не заморачиваешься
fnc(2+2,5+6);
что сначала выполнится 2+2 или 5+6
главное в функцию уйдут 4 и 11
UB страшны не сами по себе, их в каждой строчке может быть сто штук
а в том что при определенных условиях они могут дать неизвестно что
например
это всегда отработает
C++
1
a=i++;
а это зависит то компилятора
C++
1
i=i++;
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,917
Записей в блоге: 2
Завершенные тесты: 1
27.06.2013, 00:14     Постфиксный и префиксный декремент #33
Цитата Сообщение от ValeryS Посмотреть сообщение
а это зависит то компилятора
имхо, эта строчка интересней:
C++
1
foo((i = 10) + i)
ValeryS
Модератор
6377 / 4843 / 442
Регистрация: 14.02.2011
Сообщений: 16,057
27.06.2013, 00:21     Постфиксный и префиксный декремент #34
Цитата Сообщение от Croessmah Посмотреть сообщение
имхо, эта строчка интересней:
даже представить не могу сколько нужно выпить чтобы так написать
это как
C++
1
for (int i=0; i<5; i=i++)
клиент говорят долго возмущался что цикл зацикливается
Croessmah
27.06.2013, 00:26
  #35

Не по теме:

Цитата Сообщение от ValeryS Посмотреть сообщение
клиент говорят долго возмущался что цикл зацикливается

Я нарывался на такое:
C++
1
2
3
4
    int endval;
    for(int i=0,endval=0;i<5;++i)
        ++endval;
    std::cout<<endval<<std::endl;
вопрос был очевиден - почему endval не поменялся

ValeryS
Модератор
6377 / 4843 / 442
Регистрация: 14.02.2011
Сообщений: 16,057
27.06.2013, 01:20     Постфиксный и префиксный декремент #36
отвлекли вы меня от работы
начал баловаться
вот они UB
C++
1
2
3
4
5
6
int i = 0;
    std::cout << i++ << i++ << i++<<std::endl;
     i = 0;
    std::cout << ++i << ++i << ++i<<std::endl;
     i = 0;
    std::cout << i << ++i << i++<<std::endl;
результаты
210
333
220
el_gato_de_Ch
35 / 35 / 1
Регистрация: 28.04.2013
Сообщений: 110
27.06.2013, 07:17     Постфиксный и префиксный декремент #37
лурк тоже в теме =)

Добавлено через 7 минут
я на стороне Toshkarik, это UB, однако как я понимаю UB - в рамках разных компиляторов, а не в пределах одного, любопытства ради, можно запустить проверить на 1е9 тестах и посмотреть что будет, имхо ответ всегда будет 1 и тот же
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
27.06.2013, 09:42     Постфиксный и префиксный декремент #38
Все четко, нету UB в коде.
Вопрос знающим: кто-то смог хорошенько разобраться в определении UB в C++11 (sequenced before, sequenced after, etc)?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,917
Записей в блоге: 2
Завершенные тесты: 1
27.06.2013, 09:49     Постфиксный и префиксный декремент #39
@ForEveR, не разбирался еще, но можно узнать где описано конкретно? Приду с работы, попробую разобраться.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.06.2013, 09:53     Постфиксный и префиксный декремент
Еще ссылки по теме:

Перегруженный постфиксный оператор ++ C++
C++ постфиксный инкремент
Инкремент постфиксный и префиксный - принцип работы C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
27.06.2013, 09:53     Постфиксный и префиксный декремент #40
По ссылке, что я приводил, вроде, есть объяснение.
http://stackoverflow.com/questions/4...equence-points
Начинается примерно в середине.
Yandex
Объявления
27.06.2013, 09:53     Постфиксный и префиксный декремент
Ответ Создать тему
Опции темы

Текущее время: 19:28. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru