diff --git a/02-основные-типы-данных-выражения/README.md b/02-основные-типы-данных-выражения/README.md index ee9f180..51bde31 100644 --- a/02-основные-типы-данных-выражения/README.md +++ b/02-основные-типы-данных-выражения/README.md @@ -22,13 +22,13 @@ - [2.3.4.2. Выражение mixin](#2-3-4-2-выражение-mixin) - [2.3.4.3. Выражения is](#2-3-4-3-выражения-is) - [2.3.4.4. Выражения в круглых скобках](#2-3-4-4-выражения-в-круглых-скобках) - - [2.3.5. Постфиксные операции]() - - [2.3.5.1. Доступ ко внутренним элементам]() - - [2.3.5.2. Увеличение и уменьшение на единицу]() - - [2.3.5.3. Вызов функции]() - - [2.3.5.4. Индексация]() - - [2.3.5.5. Срезы массивов]() - - [2.3.5.6. Создание вложенного класса]() + - [2.3.5. Постфиксные операции](#2-3-5-постфиксные-операции) + - [2.3.5.1. Доступ ко внутренним элементам](#2-3-5-1-доступ-ко-внутренним-элементам) + - [2.3.5.2. Увеличение и уменьшение на единицу](#2-3-5-2-увеличение-и-уменьшение-на-единицу) + - [2.3.5.3. Вызов функции](#2-3-5-3-вызов-функции) + - [2.3.5.4. Индексация](#2-3-5-4-индексация) + - [2.3.5.5. Срезы массивов](#2-3-5-5-срезы-массивов) + - [2.3.5.6. Создание вложенного класса](#2-3-5-6-создание-вложенного-класса) - [2.3.6. Унарные операции]() - [2.3.6.1. Выражение new]() - [2.3.6.2. Получение адреса и разыменование]() @@ -719,6 +719,54 @@ bool [В начало ⮍](#2-3-4-4-выражения-в-круглых-скобках) [Наверх ⮍](#2-основные-типы-данных-выражения) +### 2.3.5. Постфиксные операции + +#### 2.3.5.1. Доступ ко внутренним элементам + +Оператор доступа ко внутренним элементам `a.b` предоставляет доступ к элементу с именем `b`, расположенному внутри объекта или типа `a`. Если `a` – сложное значение или сложный тип, допустимо заключить его в круглые скобки. В качестве `b` также может выступать выражение с ключевым словом `new` (см. главу 6). + +[В начало ⮍](#2-3-5-1-доступ-ко-внутренним-элементам) [Наверх ⮍](#2-основные-типы-данных-выражения) + +#### 2.3.5.2. Увеличение и уменьшение на единицу + +Постфиксный вариант операции увеличения и уменьшения на единицу (`значение++` и `значение--` соответственно) определен для всех числовых типов и указателей и имеет тот же смысл, что и одноименная операция в C и C++: применение этой операции увеличивает или уменьшает на единицу `значение` (которое должно быть l-значением), возвращая копию этого значения до его изменения. (Аналогичный префиксный вариант операции увеличения и уменьшения на единицу описан в разделе 2.3.6.3.) + +[В начало ⮍](#2-3-5-2-увеличение-и-уменьшение-на-единицу) [Наверх ⮍](#2-основные-типы-данных-выражения) + +#### 2.3.5.3. Вызов функции + +Уже знакомый оператор вызова функции `fun()` инициирует выполнение кода функции `fun`. Синтаксис `fun(<список аргументов, разделенных запятыми>)` передает в тело `fun` список аргументов. Все аргументы вычисляются слева направо перед вызовом `fun`. Количество и типы значений в списке аргументов должны соответствовать количеству и типам формальных параметров. Если функция определена с атрибутом `@property`, то указание просто имени функции эквивалентно вызову этой функции без аргументов. Обычно `fun` – это имя функции, указанное в ее определении, но может быть и функциональным литералом (см. раздел 2.2.7) или выражением, возвращающим указатель на функцию или `delegate`. Подробно функции описаны в главе 5. + +[В начало ⮍](#2-3-5-3-вызов-функции) [Наверх ⮍](#2-основные-типы-данных-выражения) + +#### 2.3.5.4. Индексация + +Выражение `arr[i]` позволяет получить доступ к `i`-му элементу массива или ассоциативного массива `arr` (элементы массива индексируются начиная с 0). Если массив неассоциативный, то значение `i` должно быть целым. Иначе значение `i` должно иметь тип, который может быть неявно преобразован к типу ключа массива `arr`. Если индексирующее выражение находится слева от оператора присваивания (например, `arr[i] = e`) и `arr` – ассоциативный массив, выполняется вставка элемента в массив, если его там не было. Иначе если i относится к элементу, которого нет в массиве `arr`, выражение порождает исключение типа `RangeError`. В качестве `arr` и `i` также могут выступать указатель и целое соответственно. Операции индексации с помощью указателей автоматически не проверяются. В некоторых режимах сборки (небезопасные итоговые сборки; см. раздел 4.1.2) отменяется проверка границ и в случае неассоциативных массивов. + +[В начало ⮍](#2-3-5-4-индексация) [Наверх ⮍](#2-основные-типы-данных-выражения) + +#### 2.3.5.5. Срезы массивов + +Если `arr` – линейный (неассоциативный) массив, выражение `arr[i .. j]` возвращает массив, ссылающийся на интервал внутри `arr` от `i`-го до `j`-го элемента (не включая последний). Значения `i` и `j`, отмечающие границы среза, должны допускать неявное преобразование в целое. Выражение `arr[]` позволяет адресовать срез массива величиной в целый массив `arr`. Данные не копируются «по-настоящему», поэтому изменение среза массива влечет к изменению содержимого исходного массива `arr`. Например: + +```d +int[] a = new int[5]; // Создать массив из пяти целых чисел +int[] b = a[3 .. 5]; // b ссылается на два последних элемента a +b[0] = 1; +b[1] = 3; +assert(a == [ 0, 0, 0, 1, 3 ]); // a был изменен +``` + +Если `i > j` или `j > a.length`, генерируется исключение типа `RangeError`. Иначе если `i == j`, будет возвращен пустой массив. В качестве `arr` в выражении `arr[i .. j]` можно использовать указатель. В этом случае будет возвращен массив, отражающий область памяти начиная с адреса `arr + i` до `arr + j` (не включая элемент с адресом `arr + j`). Если `i > j`, генерируется ошибка `RangeError`, иначе при получении среза указателя границы не проверяются. И снова в некоторых режимах сборки (небезопасные итоговые сборки, см. раздел 4.1.2) все проверки границ при получении срезов могут быть отключены. + +[В начало ⮍](#2-3-5-5-срезы-массивов) [Наверх ⮍](#2-основные-типы-данных-выражения) + +#### 2.3.5.6. Создание вложенного класса + +Выражение вида `a.new T`, где a – значение типа `class`, создает объект типа `T`, чье определение вложено в определение `a`. Что-то непонятно? Это потому что мы еще не определили ни классы, ни вложенные классы, и даже сами выражения `new` пока не рассмотрели. Определение выражения `new` уже совсем близко (в разделе 2.3.6.1), а чтобы познакомиться с определениями классов и вложенных классов, придется подождать до главы 6 (точнее до раздела 6.11). А до тех пор считайте этот раздел просто заглушкой, необходимой для целостности изложения. + +[В начало ⮍](#2-3-5-6-создание-вложенного-класса) [Наверх ⮍](#2-основные-типы-данных-выражения) + [^1]: Впрочем, использование нелатинских букв является дурным тоном. – *Прим. науч. ред.* [^2]: С99 – обновленная спецификация C, в том числе добавляющая поддержку знаков Юникода. – *Прим. пер.* [^3]: Сам язык не поддерживает восьмеричные литералы, но поскольку они присутствуют в некоторых C-подобных языках, в стандартную библиотеку был добавлен соответствующий шаблон. Теперь запись `std.conv.octal!777` аналогична записи `0777` в C. – *Прим. науч. ред.*