Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/21: Рейтинг темы: голосов - 21, средняя оценка - 4.71
BloodyWo1f
1

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

26.06.2013, 19:22. Показов 4390. Ответов 42
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
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.
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.06.2013, 19:22
Ответы с готовыми решениями:

Префиксный и постфиксный инкременты
Приветствую всех. Экспериментом установил, что префиксный инкремент переменной стандартного типа...

Префиксный и постфиксный инкремент
#include &lt;iostream&gt; using namespace std; int main() { int c=0; ...

Инкремент постфиксный и префиксный - принцип работы
Hello World! Нужна ваша помощь, мозг отказывается понимать :wall:! Набрал код: #include...

Как выполняется постфиксный и префиксный инкремент?
Растолкуйте! Обычно, а = с++ толкуется как а = с+1 тогда а = ++с есть а = 1+с Если...

42
17 / 17 / 3
Регистрация: 28.10.2012
Сообщений: 201
26.06.2013, 19:36 2
А так?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "stdafx.h"
#include <iostream>
using std::cout;
 
int main() 
{
int a=5;
 cout << --(--a) << " "; 
 cout << a << " ";
 cout << --(--a) << " "; 
 cout << --(--a) << " "; 
 cout << a << " ";
system("pause"); 
return 0;
}
1
36 / 36 / 2
Регистрация: 28.04.2013
Сообщений: 110
26.06.2013, 19:43 3
потому что есть разница между постфиксным и префиксным декрементом.

префиксной записью называется та, где оператор стоит перед операндом, --а
постфиксной соответственно наоборот а--

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

в Вашем примере a = 5; cout << (--a)--;

порядок выполнения команд будет следующий

1. присвоить 5 в а
2. выполнить префиксный декремент а (инструкция --а) а = 4
3. вывести а на экран (cout << a) (а = 4 см. предыдущую строку)
4. выполнить постфиксный декремент (инструкция а--) а = 3

поэтому после выполнения этой строчки на экран выведется число 4, а фактическое значение переменной a будет являться 3.

Добавлено через 4 минуты
для более детального понимания я приведу пример

C++
1
2
3
4
5
6
a[c++] = 5;
 
// эквивалентно 
 
a[c] = 5;
c += 1;
C++
1
2
3
4
5
a[++c] = 5;
 
// эквивалентно 
c += 1;
a[c] = 5;
2
BloodyWo1f
26.06.2013, 19:46 4
Огромное спасибо) всё понял.
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
26.06.2013, 19:53 5
Это undefined behaviour. Результат может быть каким угодно.
0
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,493
Записей в блоге: 1
26.06.2013, 22:44 6
Цитата Сообщение от Toshkarik Посмотреть сообщение
Это undefined behaviour. Результат может быть каким угодно.
Никак не могу согласиться. В чём тут проявляется UB?
C++
1
cout << (--a)--
UB возникает при определённых обстоятельствах. А именно (если я правильно понял статью http://alenacpp.blogspot.ru/20... oints.html) это происходит при обращении к значению изменённой переменной до прохождения точки следования.

В данном же случае поведение строго определено скобками и свойствами операторов предекремента/постдекремента.

Ответ:
-Сначала выполнится выражение в скобках.
-Переменная а будет уменьшена на 1 и возвращёно значение а после уменьшения, т.к. ПРЕдекремент.
-Затем значение а будет ещё раз уменьшено вторым оператором --, но на вывод будет возвращено значение а бывшее ДО декремента, т.к. ПОСТдекремент.
-Например, следующая программа выведет "-1 -2"
C++
1
2
3
int a=0;
cout << (--a)-- <<endl;
cout << a         <<endl;
Очевидно, что иногда люди, услышав где-то про классическое
- вопрос: какой результат у выражения i=i++ + i++;?
- ответ: UB
начинают распространять этот ответ на любые подобные(и не совсем подобные) выражения, не задумываясь о настоящих причинах UB или не UB. Так, что вот.
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
26.06.2013, 22:49 7
@Kuzia domovenok, переменная изменяет свое значение больше одного раза в пределах одной точки следования. http://stackoverflow.com/quest... nce-points
А именно:
From the above sentence the following expressions invoke Undefined Behaviour.

C++
1
2
3
4
5
6
7
i++ * ++i; // i is modified more than once
i = ++i    // same as above
++i = 2;   // same as above
i = ++i +1 // same as above
++++++i;   //parsed as (++(++(++i)))
 
i = (i,++i,++i); // Undefined Behaviour because there's no sequence point between `++i`(right most) and assignment to `i` (`i` gets modified more than once b/w two SP)
И, поверьте, я знаю, что говорю, а не "где то что то там услышал или прочитал".
0
4064 / 3318 / 924
Регистрация: 25.03.2012
Сообщений: 12,493
Записей в блоге: 1
26.06.2013, 22:57 8
Цитата Сообщение от Toshkarik Посмотреть сообщение
И, поверьте, я знаю, что говорю, а не "где то что то там услышал или прочитал".
Именно, что ты где-то услышал про
i++ * ++i; // i is modified more than once
i = ++i // same as above
++i = 2; // same as above
i = ++i +1 // same as above
++++++i; //parsed as (++(++(++i)))

i = (i,++i,++i);
И даже не указал, к какому из перечисленных тобой вариантов UB относится обсуждаемый пример. Не удивительно! Ведь внимание! ответ... ни к какому из них!

Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от Toshkarik Посмотреть сообщение
И, поверьте
не выкайте мне, а то я тоже как начну всем выкать! Ужас!

0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
26.06.2013, 23:01 9
Специально для Вас:
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.
Добавлено через 2 минуты
Ну и если еще не совсем поняли, то если
++++++i; //parsed as (++(++(++i)))
UB, тогда
Цитата Сообщение от BloodyWo1f Посмотреть сообщение
(--a)--
уж подавно.
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
26.06.2013, 23:03 10
Цитата Сообщение от Toshkarik Посмотреть сообщение
Специально для Вас:
только в данном случае она же меняется последовательно, а не как решит компилятор
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
26.06.2013, 23:07 11
@Croessmah, не аналогично, так как операция запятая в данном случая является точкой следования.
Если ++++i парсится компилятором как ++( ++i ), и это является UB, то чем лучше ( --i )-- ? В любом случае переменная меняется два раза в одном выражении и в пределах одной точки следования.
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
26.06.2013, 23:09 12
Цитата Сообщение от Toshkarik Посмотреть сообщение
и это является UB, то чем лучше ( --i )--
тем, что для вычисления постинкремента нужно сначала вычислить выражение в скобках, иначе имеем постинкремент неизвестного значения, то бишь сначала выполниться выражение в скобках
0
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
26.06.2013, 23:13 13
@Toshkarik,
а по твоему точка следования это только точка с запятой?
@Kuzia domovenok,
Здесь полностью прав(не часто мы с ним соглашаемся)
идет уменьшение
потом вывод на экран ( в поток) вот она точка следования
и потом еще раз уменьшение
никаких разночтений
вот интересная статья
http://alenacpp.blogspot.ru/20... oints.html
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
26.06.2013, 23:13 14
@Croessmah, дело не в скобках, а дело в изменении переменной больше одного раза в одном полном выражении, в данном случае в выражениях ++( ++i ); и ( --i )--; переменная меняется два раза, а по стандарту:
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.
это UB.
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
26.06.2013, 23:14 15
Цитата Сообщение от Toshkarik Посмотреть сообщение
@Croessmah, дело не в скобках, а дело в изменении переменной больше одного раза в одном полном выражении
В данном случае ЯВНО ЗАДАН ПОРЯДОК изменения
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
26.06.2013, 23:15 16
@ValeryS, а я разве где то говорил об точке с запятой? Я никому ничего не навязываю, лишь говорю о том, что написано в стандарте. Хотя в новом стандарте вроде как убрали понятие sequence point
0
Модератор
Эксперт по электронике
8908 / 6677 / 918
Регистрация: 14.02.2011
Сообщений: 23,521
26.06.2013, 23:17 17
@Croessmah,
а вот интересно а так что будет
C++
1
--i--;
и будет ли вообще что то?
у предикремента ведь приоритет выше ?
вопрос чисто академический, ибо так писать не собираюсь
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
26.06.2013, 23:18 18
Цитата Сообщение от Croessmah Посмотреть сообщение
В данном случае ЯВНО ЗАДАН ПОРЯДОК изменения
Да причем тут "явно задан порядок" то. При вычислении этого выражения переменная изменяется дважды. Я приводил уже цитату по этому поводу, не я писал стандарт.
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
26.06.2013, 23:21 19
Цитата Сообщение от ValeryS Посмотреть сообщение
у предикремента ведь приоритет выше ?
у постфиксного выше
http://ru.cppreference.com/w/c... precedence
а значит имеем прединкремент временной переменной

Добавлено через 42 секунды
Цитата Сообщение от Toshkarik Посмотреть сообщение
При вычислении этого выражения переменная изменяется дважды.
Вот тут UB, ибо порядок
(--a) + (a--)
не задан
0
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
26.06.2013, 23:23 20
@ValeryS, этот код не должен компилироваться.
0
26.06.2013, 23:23
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.06.2013, 23:23
Помогаю со студенческими работами здесь

Потокобезопасен ли префиксный инкремент/декремент?
Потокобезопасен ли префиксный инкремент/декремент? Например такой код: // Объявляем глобальную...

Поясните как работает постфиксный и префиксный оператор на примере
Здравствуйте. Здесь префиксный понятно, а что если изменить на постфиксный, как код будет работать?...

Указатели: почему так происходит? Постфиксный и префиксный инкремент
В общем, вот код программы double q; for (int i(0);i&lt;10;i++) { q=i; } cout&lt;&lt;q&lt;&lt;endl;...

Постфиксный, и префиксный экземпляры оператора приращения: в чем разница?
постфиксный, и префиксный экземпляры оператора приращения в чем разница? i++ ++i ??


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru