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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.79
BloodyWo1f
Сообщений: n/a
#1

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

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

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.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.06.2013, 19:22
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Постфиксный и префиксный декремент (C++):

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

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

Инкремент постфиксный и префиксный - принцип работы - C++
Hello World! Нужна ваша помощь, мозг отказывается понимать :wall:! Набрал код: #include &lt;iostream&gt; using namespace std; int...

Потокобезопасен ли префиксный инкремент/декремент? - C++
Потокобезопасен ли префиксный инкремент/декремент? Например такой код: // Объявляем глобальную переменную uint64_t i=0; // Тут...

Поясните как работает постфиксный и префиксный оператор на примере - C++
Здравствуйте. Здесь префиксный понятно, а что если изменить на постфиксный, как код будет работать? vector&lt;int&gt;::size_type...

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

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
FireProoF
17 / 17 / 1
Регистрация: 28.10.2012
Сообщений: 193
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;
}
el_gato_de_Ch
35 / 35 / 1
Регистрация: 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;
BloodyWo1f
Сообщений: n/a
26.06.2013, 19:46 #4
Огромное спасибо) всё понял.
Toshkarik
1140 / 857 / 51
Регистрация: 03.08.2011
Сообщений: 2,384
Завершенные тесты: 1
26.06.2013, 19:53 #5
Это undefined behaviour. Результат может быть каким угодно.
Kuzia domovenok
1891 / 1746 / 118
Регистрация: 25.03.2012
Сообщений: 5,925
Записей в блоге: 1
26.06.2013, 22:44 #6
Цитата Сообщение от Toshkarik Посмотреть сообщение
Это undefined behaviour. Результат может быть каким угодно.
Никак не могу согласиться. В чём тут проявляется UB?
C++
1
cout << (--a)--
UB возникает при определённых обстоятельствах. А именно (если я правильно понял статью http://alenacpp.blogspot.ru/2005/11/...ce-points.html) это происходит при обращении к значению изменённой переменной до прохождения точки следования.

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

Ответ:
-Сначала выполнится выражение в скобках.
-Переменная а будет уменьшена на 1 и возвращёно значение а после уменьшения, т.к. ПРЕдекремент.
-Затем значение а будет ещё раз уменьшено вторым оператором --, но на вывод будет возвращено значение а бывшее ДО декремента, т.к. ПОСТдекремент.
-Например, следующая программа выведет "-1 -2"
C++
1
2
3
int a=0;
cout << (--a)-- <<endl;
cout << a         <<endl;
Очевидно, что иногда люди, услышав где-то про классическое
- вопрос: какой результат у выражения i=i++ + i++;?
- ответ: UB
начинают распространять этот ответ на любые подобные(и не совсем подобные) выражения, не задумываясь о настоящих причинах UB или не UB. Так, что вот.
Toshkarik
1140 / 857 / 51
Регистрация: 03.08.2011
Сообщений: 2,384
Завершенные тесты: 1
26.06.2013, 22:49 #7
@Kuzia domovenok, переменная изменяет свое значение больше одного раза в пределах одной точки следования. http://stackoverflow.com/questions/4...equence-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)
И, поверьте, я знаю, что говорю, а не "где то что то там услышал или прочитал".
Kuzia domovenok
1891 / 1746 / 118
Регистрация: 25.03.2012
Сообщений: 5,925
Записей в блоге: 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 Посмотреть сообщение
И, поверьте
не выкайте мне, а то я тоже как начну всем выкать! Ужас!

Toshkarik
1140 / 857 / 51
Регистрация: 03.08.2011
Сообщений: 2,384
Завершенные тесты: 1
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)--
уж подавно.
Croessmah
Модератор
Эксперт CЭксперт С++
13155 / 7418 / 831
Регистрация: 27.09.2012
Сообщений: 18,255
Записей в блоге: 3
Завершенные тесты: 1
26.06.2013, 23:03 #10
Цитата Сообщение от Toshkarik Посмотреть сообщение
Специально для Вас:
только в данном случае она же меняется последовательно, а не как решит компилятор
Toshkarik
1140 / 857 / 51
Регистрация: 03.08.2011
Сообщений: 2,384
Завершенные тесты: 1
26.06.2013, 23:07 #11
@Croessmah, не аналогично, так как операция запятая в данном случая является точкой следования.
Если ++++i парсится компилятором как ++( ++i ), и это является UB, то чем лучше ( --i )-- ? В любом случае переменная меняется два раза в одном выражении и в пределах одной точки следования.
Croessmah
Модератор
Эксперт CЭксперт С++
13155 / 7418 / 831
Регистрация: 27.09.2012
Сообщений: 18,255
Записей в блоге: 3
Завершенные тесты: 1
26.06.2013, 23:09 #12
Цитата Сообщение от Toshkarik Посмотреть сообщение
и это является UB, то чем лучше ( --i )--
тем, что для вычисления постинкремента нужно сначала вычислить выражение в скобках, иначе имеем постинкремент неизвестного значения, то бишь сначала выполниться выражение в скобках
ValeryS
Модератор
6556 / 5022 / 464
Регистрация: 14.02.2011
Сообщений: 16,763
26.06.2013, 23:13 #13
@Toshkarik,
а по твоему точка следования это только точка с запятой?
@Kuzia domovenok,
Здесь полностью прав(не часто мы с ним соглашаемся)
идет уменьшение
потом вывод на экран ( в поток) вот она точка следования
и потом еще раз уменьшение
никаких разночтений
вот интересная статья
http://alenacpp.blogspot.ru/2005/11/...ce-points.html
Toshkarik
1140 / 857 / 51
Регистрация: 03.08.2011
Сообщений: 2,384
Завершенные тесты: 1
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.
Croessmah
Модератор
Эксперт CЭксперт С++
13155 / 7418 / 831
Регистрация: 27.09.2012
Сообщений: 18,255
Записей в блоге: 3
Завершенные тесты: 1
26.06.2013, 23:14 #15
Цитата Сообщение от Toshkarik Посмотреть сообщение
@Croessmah, дело не в скобках, а дело в изменении переменной больше одного раза в одном полном выражении
В данном случае ЯВНО ЗАДАН ПОРЯДОК изменения
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.06.2013, 23:14
Привет! Вот еще темы с ответами:

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

не работает префиксный оператор в классе - C++
Проблема : не работает &quot;++plus&quot; в &quot;void ClassB::count()&quot; Есть вариант решить это так : поменять &quot;private&quot; на &quot;protected&quot; в обоих классах...

постфиксный инкремент - C++
class Inkrement { Inkrement(){}; Inkrement &amp;operator++(int) { Inkrement temp = *this; ++*this; return temp; ...

Указатель на постфиксный инкремент x - C++
Почему так нельзя делать? int *p = &amp;(x++); Вроде же все ясно должно быть компилятору


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
26.06.2013, 23:14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru