Операторы увеличения и уменьшения
Эта статья нуждается в дополнительных цитатах для проверки . ( сентябрь 2014 г. ) |
Операторы увеличения и уменьшения — это унарные операторы , которые увеличивают или уменьшают свой операнд на единицу.
Они обычно встречаются в императивных языках программирования . C -подобные языки имеют две версии (до- и пост-) каждого оператора с несколько разной семантикой.
В языках, синтаксически производных от B (включая C и его различные производные), оператор приращения записывается как ++
и оператор декремента записывается как --
. Некоторые другие языки используют функции inc(x) и dec(x).
Оператор инкремента увеличивает, а оператор декремента уменьшает значение своего операнда на 1. Операнд должен иметь арифметический указателя тип данных или тип данных и должен ссылаться на изменяемый объект данных . Значения указателей увеличиваются (или уменьшаются) на величину, заставляющую их указывать на следующий (или предыдущий) элемент, соседний в памяти.
На языках, поддерживающих обе версии операторов:
- Операторы pre -increment и pre -decrement увеличивают (или уменьшают) свой операнд на 1, а значением выражения является результирующее увеличенное (или уменьшенное) значение.
- Операторы post -increment и post -decrement увеличивают (или уменьшают) значение своего операнда на 1, но значением выражения является значение операнда до операции увеличения (или уменьшения).
В языках, где приращение/уменьшение не является выражением (например, Go ), необходима только одна версия (в случае Go — только операторы post).
Поскольку оператор увеличения/уменьшения изменяет свой операнд, использование такого операнда более одного раза в одном и том же выражении может привести к неопределенным результатам. Например, в таких выражениях, как x - ++x
, неясно, в какой последовательности следует выполнять операции вычитания и приращения. Такие выражения обычно вызывают неопределенное поведение , и их следует избегать.
В языках с типизированными указателями, таких как C, оператор приращения перемещает указатель на следующий элемент этого типа, увеличивая значение указателя на размер этого типа. Когда указатель (правильного типа) указывает на любой элемент массива, приращение (или уменьшение) приводит к тому, что указатель указывает на «следующий» (или «предыдущий») элемент этого массива. Таким образом, увеличение указателя на целое число делает его указателем на следующее целое число (обычно значение указателя увеличивается на 4); [1] увеличение указателя на структуру размером 106 байт приводит к тому, что он указывает на следующую структуру путем увеличения значения указателя на 106. [2]
Примеры
[ редактировать ]Следующий фрагмент кода C иллюстрирует разницу между операторами увеличения и уменьшения до и после :
int x;
int y;
// Increment operators
// Pre-increment: x is incremented by 1, then y is assigned the value of x
x = 1;
y = ++x; // x is now 2, y is also 2
// Post-increment: y is assigned the value of x, then x is incremented by 1
x = 1;
y = x++; // y is 1, x is now 2
// Decrement operators
// Pre-decrement: x is decremented by 1, then y is assigned the value of x
x = 1;
y = --x; // x is now 0, y is also 0
// Post-decrement: y is assigned the value of x, then x is decremented by 1
x = 1;
y = x--; // y is 1, x is now 0
В языках, где нет этих операторов, эквивалентные результаты требуют дополнительной строки кода:
# Pre-increment: y = ++x
x = 1
x = x + 1 # x is now 2 (can be written as "x += 1" in Python)
y = x # y is also 2
# Post-increment: y = x++
x = 1
y = x # y is 1
x = x + 1 # x is now 2
Оператор пост-инкремента обычно используется с индексами массива . Например:
// Sum the elements of an array
float sum_elements(float arr[], int n)
{
float sum = 0.0;
int i = 0;
while (i < n)
sum += arr[i++]; // Post-increment of i, which steps
// through n elements of the array
return sum;
}
Оператор пост-инкремента также часто используется с указателями :
// Copy one array to another
void copy_array(float *src, float *dst, int n)
{
while (n-- > 0) // Loop that counts down from n to zero
*dst++ = *src++; // Copies element *(src) to *(dst),
// then increments both pointers
}
Эти примеры также работают на других C-подобных языках, таких как C++ , Java и C# .
- Оператор инкремента можно продемонстрировать на примере:
#include <stdio.h> int main() { int c = 2; printf("%d\n", c++); // this statement displays 2, then c is incremented by 1 to 3. printf("%d", ++c); // this statement increments c by 1, then c is displayed. return 0; }
- Выход:
2 4
- Выход:
Поддерживаемые языки
[ редактировать ]В следующем списке, хотя и не является полным и всеобъемлющим, перечислены некоторые основные языки программирования, поддерживающие операторы увеличения и уменьшения.
|
от Apple Swift когда-то поддерживал эти операторы, но с версии 2.2 они устарели. [13] и удален начиная с версии 3.0. [14] [15]
Паскаль , Delphi , Modula-2 и Oberon используют функции ( inc(x)
и dec(x)
) вместо операторов.
Примечательно, что Python и Rust не поддерживают эти операторы.
История
[ редактировать ]Эта концепция была введена в язык программирования B примерно в 1969 году Кеном Томпсоном . [16]
Томпсон пошел еще дальше, изобретя операторы ++ и --, которые увеличивают или уменьшают; их префиксная или постфиксная позиция определяет, происходит ли изменение до или после записи значения операнда. Их не было в самых ранних версиях B, но они появились по ходу дела. Люди часто предполагают, что они были созданы для использования режимов автоинкремента и автодекремента адреса, обеспечиваемых DEC PDP-11, на котором C и Unix впервые стали популярными. Это исторически невозможно, поскольку на момент разработки B не было PDP-11. Однако у PDP-7 было несколько ячеек памяти с «автоинкрементом», причем косвенное обращение к памяти через них увеличивало ячейку. Эта особенность, вероятно, подсказала Томпсону такие операторы; обобщение, позволяющее сделать их одновременно префиксными и постфиксными, было его собственным. Действительно, ячейки автоинкремента не использовались непосредственно при реализации операторов, и более сильной мотивацией для нововведения, вероятно, было его наблюдение о том, что перевод ++x был меньше, чем перевод x=x+1.
См. также
[ редактировать ]- Дополненное задание – для
+=
и-=
операторы - ПДП-7
- ПДП-11
- Функция-преемник
Ссылки
[ редактировать ]- ^ Ричард М Риз. «Понимание и использование указателей C» . «Глава 4. Указатели и массивы» . О'Рейли Медиа, Инк. 2013. ISBN 9781449344184
- ^ Ричард Петерсен. «Введение в C с C++» . 2019. Рисунок 12-12.
- ^ «Руководство пользователя GNU Awk» . Фонд свободного программного обеспечения.
- ^ «8.3. Конструкция двойных круглых скобок» . Проект документации Linux.
- ^ Ричи, Брайан В. Керниган; Деннис М.; Ричи, Деннис (1988). Язык программирования Си (2-е изд., [Начдр.] изд.). Энглвуд Клиффс, Нью-Джерси: Прентис Холл. п. 18 . ISBN 0-13-110362-8 .
{{cite book}}
: CS1 maint: несколько имен: список авторов ( ссылка ) - ^ «Операторы увеличения/уменьшения» . cppreference.com.
- ^ «Оператор ++ (Справочник по C#)» . Сеть разработчиков Microsoft.
- ^ «Перегрузка оператора» . dlang.org.
- ^ «Операторы GP и их приоритеты» .
- ^ «Об операторах присваивания» .
- ^ «Увеличение символа языка Wolfram» . Центр языковой документации Wolfram.
- ^ «Уменьшить символ языка Wolfram» . Центр языковой документации Wolfram.
- ^ «Новые возможности Swift 2.2» . Официальный сайт Swift.
- ^ «Выпущен Swift 3.0!» . Официальный сайт Swift.
- ^ «Удалить
++
и--
операторы» . Быстрая эволюция . - ^ Ричи, Деннис М. (март 1993 г.). «Развитие языка Си» . Уведомления ACM SIGPLAN . 28 (3): 5. дои : 10.1145/155360.155580 .