Что такое декремент в программировании
Синтаксис
Remarks
Оператор префикса декремента ( — ) аналогичен оператору префикса инкремента, за исключением того, что операнд уменьшается на единицу, а результатом является это уменьшенное значение.
Операторы префиксных и постфиксных инкремента и декремента влияют на свои операнды. Они различаются между собой порядком выполнения инкремента или декремента при вычислении выражения (Дополнительные сведения см. в разделе Постфиксные операторы инкремента и декремента.) В префиксной форме инкремент или декремент выполняется до использования значения при вычислении выражения, поэтому значение выражения отличается от значение операнда. В постфиксной форме инкремент или декремент выполняется после использования значения при вычислении выражения, поэтому значение выражения совпадает со значением операнда. Например, в следующей программе выполняется вывод на печать » ++i = 6 «.
Операнд целочисленного типа или типа с плавающей запятой инкрементируется или декрементируется на целое значение 1. Тип результата совпадает с типом операнда. Операнд типа указателя инкрементируется или декрементируется на значение размера объекта, к которому он относится. Инкрементированный указатель указывает на следующий объект, а декрементированный — на предыдущий.
Поскольку операторы инкремента и декремента имеют побочные эффекты, использование выражений с операторами инкремента или декремента в макросе препроцессора может иметь нежелательные результаты. Рассмотрим следующий пример.
Макрос разворачивается до следующего выражения:
Если значение i больше или равно j или меньше j на 1, оно будет инкрементировано дважды.
Встраиваемые функции C++ предпочтительнее макросов во многих случаях, поскольку исключают побочные эффекты, подобные описанным здесь, и позволяют языку выполнять более полную проверку типов.
5.4 – Операторы инкремента/декремента и их побочные эффекты
Инкремент и декремент переменных
Инкремент (увеличение на 1) и декремент (уменьшение на 1) переменной настолько распространены, что имеют свои собственные операторы.
Обратите внимание, что существует две версии каждого оператора – префиксная версия (где оператор стоит перед операндом) и постфиксная версия (где оператор стоит после операнда).
Префиксные операторы инкремента/декремента очень просты. Сначала операнд увеличивается или уменьшается на единицу, а затем выражение вычисляется как значение операнда. Например:
Эта программа напечатает:
Постфиксные операторы инкремента/декремента немного сложнее. Сначала создается копия операнда. Затем операнд (не копия) увеличивается или уменьшается на единицу. И, наконец, вычисляется копия (а не оригинал). Например:
Эта программа напечатает:
Следовательно, y заканчивается значением 5 (значение до инкремента), а x заканчивается значением 6 (значение после инкремента).
Обратите внимание, что постфиксная версия требует гораздо большего количества шагов и, следовательно, может быть не такой производительной, как префиксная версия.
Вот еще один пример, показывающий разницу между префиксной и постфиксной версиями:
Эта программа в результате напечатает:
В 10-й строке мы выполняем постфиксные инкремент и декремент. В этой строке в std::cout отправляются копии x и y (с ранее увеличенными и уменьшенными значениями), поэтому мы не видим здесь проявлений инкремента и декремента. Эти изменения не проявятся до следующей строки, когда x и y вычисляются снова.
Лучшая практика
Решительно отдавайте предпочтение префиксной версии операторов инкремента и декремента, поскольку они, как правило, более производительны, и у вас меньше шансов столкнуться со странными проблемами, связанными с ними.
Побочные эффекты
Говорят, что функция или выражение имеют побочный эффект, если они делают что-либо, что сохраняется за пределами срока действия самой функции или выражения.
Обобщенные примеры побочных эффектов включают в себя изменение значений объектов, выполнение ввода или вывода или обновление графического пользовательского интерфейса (например, включение или выключение кнопки).
В большинстве случаев побочные эффекты полезны:
Однако побочные эффекты также могут привести к неожиданным результатам:
Бывают и другие случаи, когда C++ не определяет порядок, в котором вычисляются определенные вещи (например, операнды операторов), поэтому разные компиляторы могут демонстрировать разное поведение. Даже там, где C++ проясняет, как следует вычислять вещи, исторически это была область, где было много багов компиляторов. Как правило, всех этих проблем можно избежать, если гарантировать, что любая переменная, к которой применен побочный эффект, используется в какой-либо заданной инструкции не более одного раза.
Предупреждение
C++ не определяет порядок вычисления аргументов функции или операндов операторов.
Предупреждение
Не используйте в какой-либо инструкции переменную, к которой применяется побочный эффект, более одного раза. Если вы это сделаете, результат может быть неопределенным.
Инкремент и декремент в С++
В предыдущей статье мы с вами рассмотрели бинарные операторы, которые используют для арифметических операций с двумя операндами (переменными). А в этом уроке мы научимся применять унарные операторы, для которых необходим один операнд. Называются они инкремент ( ++ ) и декремент ( – – ). Роль этих операторов в том, чтобы изменить (увеличить или уменьшить соответственно) значение переменной на единицу, при этом значение будет перезаписано. Рассмотрим пример, в котором будем изменять значение переменной variable на единицу тремя различными способами:
После каждой операции в строках 11, 13 и 15. к значению переменной variable прибавляется единица. Как вы видите, самая короткая запись – это запись с использованием инкремента. Ниже, в строках 17 – 19, мы трижды применили декремент и в итоге получим значение variable уменьшенное на 3.
Оба этих унарных оператора могут иметь две формы: постфиксную ( когда оператор расположен сразу за переменной) и префиксную (оператор расположен перед переменной). В рассмотренном примере мы применяли постфиксные формы инкремента и декремента. Чем же отличаются эти формы друг от друга? И первая и вторая формы этих операторов выполняют одинаковые роли – увеличение или уменьшение переменной на единицу. Но если в строке кода, где применяются инкремент или декремент, присутствуют еще какое-либо команды, тогда эти операторы по-разному себя ведут. Постфиксная форма будет применена после выполнения других команд. Посмотрим на следующем примере:
Программирование на C, C# и Java
Уроки программирования, алгоритмы, статьи, исходники, примеры программ и полезные советы
ОСТОРОЖНО МОШЕННИКИ! В последнее время в социальных сетях участились случаи предложения помощи в написании программ от лиц, прикрывающихся сайтом vscode.ru. Мы никогда не пишем первыми и не размещаем никакие материалы в посторонних группах ВК. Для связи с нами используйте исключительно эти контакты: vscoderu@yandex.ru, https://vk.com/vscode
Инкремент и декремент
Инкремент – это операция в языках программирования, которая увеличивает переменную на единицу, если переменная числовая и возвращает следующий символ из таблицы символов, если переменная символьного типа. При этом переменная не должна принадлежать типу данных const (т.е. константе).
Операторы инкремента записывается как два плюса: ++
Существуют два вида инкрементов: преинкремент (или префиксный инкремент) и постинкремент (или постфиксный инкремент).
В синтаксисе префиксный инкремент ставится перед необходимой переменной, а постфиксный, соответственно, после.
Главное различие между ними, что при использовании операции преинкремента значение переменной сначала увеличивается на 1, а затем используется в выражении, к которому относится данная переменная. А при использовании операции постинкремента значение переменной сначала используется в выражении, а потом увеличивается на 1.
Более подробно и с примерами про это будет рассказано ниже.
Декремент – это подобная инкременту операция, с той лишь разницей, что она уменьшает числовую переменную на единицу, а для символьной переменной выбирает предшествующий ей символ из таблицы символов. Декремент также не работает с константным типом данных и также имеет два вида: предекремент (префиксный декремент) и постдекремент (постфиксный декремент).
Урок №40. Инкремент, декремент и побочные эффекты
Обновл. 11 Сен 2021 |
На этом уроке мы рассмотрим, что такое инкремент и декремент в языке С++, а также разберемся с таким понятием, как «побочные эффекты».
Инкремент и декремент
Операции инкремента (увеличение на 1 ) и декремента (уменьшение на 1 ) переменных настолько используемые, что у них есть свои собственные операторы в языке C++. Кроме того, каждый из этих операторов имеет две версии применения: префикс и постфикс.
Оператор | Символ | Пример | Операция |
Префиксный инкремент (пре-инкремент) | ++ | ++x | Инкремент x, затем вычисление x |
Префиксный декремент (пре-декремент) | −− | −−x | Декремент x, затем вычисление x |
Постфиксный инкремент (пост-инкремент) | ++ | x++ | Вычисление x, затем инкремент x |
Постфиксный декремент (пост-декремент) | −− | x−− | Вычисление x, затем декремент x |
С операторами инкремента/декремента версии префикс всё просто. Значение переменной х сначала увеличивается/уменьшается, а затем уже вычисляется. Например:
Вот еще один пример, показывающий разницу между версиями префикс и постфикс:
Результат выполнения программы:
5 5
6 4
6 4
6 4
7 3
В строке №7 переменные х и у увеличиваются/уменьшаются на единицу непосредственно перед обработкой компилятором, так что сразу выводятся их новые значения. А в строке №9 временные копии ( х = 6 и у = 4 ) отправляются в cout, а только после этого исходные х и у увеличиваются/уменьшаются на единицу. Именно поэтому изменения значений переменных после выполнения операторов версии постфикс не видно до следующей строки.
Версия префикс увеличивает/уменьшает значения переменных перед обработкой компилятором, версия постфикс — после обработки компилятором.
Правило: Используйте префиксный инкремент и префиксный декремент вместо постфиксного инкремента и постфиксного декремента. Версии префикс не только более производительны, но и ошибок с ними (по статистике) меньше.
Побочные эффекты
Функция или выражение имеет побочный эффект, если она/оно изменяет состояние чего-либо, делает ввод/вывод или вызывает другие функции, которые имеют побочные эффекты.
В большинстве случаев побочные эффекты являются полезными:
Также побочные эффекты могут приводить и к неожиданным результатам:
Вот еще один пример:
Есть и другие случаи, в которых C++ не определяет порядок обработки данных, поэтому в разных компиляторах могут быть разные результаты. Но даже в тех случаях, когда C++ и уточняет порядок обработки данных, некоторые компиляторы все равно вычисляют переменные с побочными эффектами некорректно. Этого всего можно избежать, если использовать переменные с побочными эффектами не более одного раза в одном стейтменте.
Правило: Не используйте переменную с побочным эффектом больше одного раза в одном стейтменте.
Поделиться в социальных сетях:
Урок №39. Арифметические операторы
Комментариев: 31
Постфикс круче!
Поэтому язык называется С++, а не ++С.
Попытка разобраться почему x = x++ вызывал «undefined behavior».
До с++17 компилятор VS выдавал такой код:
x = x (1) — вычисляем правый операнд, присваивание здесь НЕ выполняется, мы просто ставим на место справа от равно 1.
x = 1 — выполняем присваивание, значение «х» равно 1.
Собственно на этом всё, согласно стандарту мы выполнили присваивание, но остался «побочный эффект» у оператора справа x++. И то когда выполнять пост-инкремент было не определено. VS компилятор делал это после т.е следующей была команда:
x++ — и «х» равен 2, что и выводилось в консоль.
В с++17 определили порядок: вычисление правого операнда далее вычисление выражения(т.е «побочного эффекта») и только потом операция присваивания:
Теперь порядок выполнения операторов соответствует приоритету операций и сам инкремент выполняется правильно, через копию переменной. Как я понял так изначально было реализовано в компиляторе gcc, который выводил 1.
Почему ниже написанная программа выдаёт разный результат? У меня он такой: