dlang-book/02-основные-типы-данных-выр...
Alexander Zhirov 871eb75c78 2.2.1, 2.2.2 2023-01-22 16:41:56 +03:00
..
images 2.2.1, 2.2.2 2023-01-22 16:41:56 +03:00
README.md 2.2.1, 2.2.2 2023-01-22 16:41:56 +03:00

README.md

2. Основные типы данных. Выражения

  • 2.1. Идентификаторы
  • 2.2. Литералы
    • 2.2.1. Логические литералы
    • 2.2.2. Целые литералы
    • 2.2.3. Литералы с плавающей запятой
    • 2.2.4. Знаковые литералы
    • 2.2.5. Строковые литералы
      • 2.2.5.1. Строковые литералы: WYSIWYG, с разделителями, строки токенов и импортированные
      • 2.2.5.2. Тип строкового литерала
    • 2.2.6. Литералы массивов и ассоциативных массивов
    • 2.2.7. Функциональные литералы (лямбда-функция)
  • 2.3. Операции
    • 2.3.1. l-значения и r-значения
    • 2.3.2. Неявные преобразования чисел
      • 2.3.2.1. Распространение интервала значений
    • 2.3.3. Типы числовых операций
    • 2.3.4. Первичные выражения
      • 2.3.4.1. Выражение assert
      • 2.3.4.2. Выражение mixin
      • 2.3.4.3. Выражения is
      • 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.6. Унарные операции
      • 2.3.6.1. Выражение new
      • 2.3.6.2. Получение адреса и разыменование
      • 2.3.6.3. Увеличение и уменьшение на единицу (префиксный вариант)
      • 2.3.6.4. Поразрядное отрицание
      • 2.3.6.5. Унарный плюс и унарный минус
      • 2.3.6.6. Отрицание
      • 2.3.6.7. Приведение типов
    • 2.3.7. Возведение в степень
    • 2.3.8. Мультипликативные операции
    • 2.3.9. Аддитивные операции
    • 2.3.10. Сдвиг
    • 2.3.11. Выражения in
    • 2.3.12. Сравнение
      • 2.3.12.1. Проверка на равенство
      • 2.3.12.2. Сравнение для упорядочивания
      • 2.3.12.3. Неассоциативность
    • 2.3.13. Поразрядные ИЛИ, ИСКЛЮЧАЮЩЕЕ ИЛИ и И
    • 2.3.14. Логическое И
    • 2.3.15. Логическое ИЛИ
    • 2.3.16. Тернарная условная операция
    • 2.3.17. Присваивание
    • 2.3.18. Выражения с запятой
  • 2.4. Итоги и справочник

Если вы когда-нибудь программировали на C, C++, Java или C#, то с основными типами данных и выражениями D у вас не будет никаких затруднений. Операции со значениями основных типов неотъемлемая часть решений многих задач программирования. Эти средства языка, в зависимости от ваших предпочтений, могут сильно облегчать либо отравлять вам жизнь. Совершенного подхода не существует; нередко поставленные цели противоречат друг другу, заставляя руководствоваться собственным субъективным мнением. Это, в свою очередь, лишает язык возможности угодить всем до единого. Слишком строгая система обременяет программиста своими запретами: он вынужден бороться с компилятором, чтобы тот принял простейшие выражения. А сделай систему типизации чересчур снисходительной и не заметишь, как окажешься по ту сторону корректности, эффективности или того и другого вместе.

Система основных типов D творит маленькие чудеса в границах, задаваемых его принадлежностью к семейству статически типизированных компилируемых языков. Определение типа по контексту, распространение интервала значений, всевозможные стратегии перегрузки операторов и тщательно спроектированная сеть автоматических преобразований вместе делают систему типизации D дотошным, но сдержанным помощником, который если и придирается, требуя внимания, то обычно не зря.

Основные типы данных можно распределить по следующим категориям:

  • Тип без значения: void, используется во всех случаях, когда формально требуется указать тип, но никакое осмысленное значение не порождается.
  • Тип null: typeof(null) тип константы null, используется в основном в шаблонах, неявно приводится к указателям, массивам, ассоциативным массивам и объектным типам.
  • Логический (булев) тип: bool с двумя возможными значениями true и false.
  • Целые типы: byte, short, int и long, а также их эквиваленты без знака ubyte, ushort, uint и ulong.
  • Вещественные типы с плавающей запятой: float, double и real.
  • Знаковые типы: char, wchar и dchar, которые на самом деле содержат числа, предназначенные для кодирования знаков Юникода.

В табл. 2.1 вкратце описаны основные типы данных D с указанием их размеров и начальных значений по умолчанию. В языке D переменная инициализируется автоматически, если вы просто определили ее, не указав начального значения. Значение по умолчанию доступно для любого типа как <тип>.init; например int.init это ноль.

Таблица 2.1. Основные типы данных D

Тип данных Описание Начальное значение по умолчанию
void Без значения n/a
typeof(null) Тип константы null n/a
bool Логическое (булево) значение false
byte Со знаком, 8 бит 0
ubyte Без знака, 8 бит 0
short Со знаком, 16 бит 0
ushort Без знака, 16 бит 0
int Со знаком, 32 бита 0
uint Без знака, 32 бита 0
long Со знаком, 64 бита 0
ulong Без знака, 64 бита 0
float 32 бита, с плавающей запятой float.nan
double 64 бита, с плавающей запятой double.nan
real Наибольшее, какое только может позволить аппаратное обеспечение real.nan
char Без знака, 8 бит, в UTF-8 0xFF
wchar Без знака, 16 бит, в UTF-16 0xFFFF
dchar Без знака, 32 бита, в UTF-32 0x0000FFFF

В начало ⮍

2.1. Идентификаторы

Идентификатор, или символ это чувствительная к регистру строка знаков, начинающаяся с буквы или знака подчеркивания, после чего следует любое количество букв, знаков подчеркивания или цифр. Единственное исключение из этого правила: идентификаторы, начинающиеся с двух знаков подчеркивания, зарезервированы под ключевые слова самого D. Идентификаторы, начинающиеся с одного знака подчеркивания, разрешены, и в настоящее время даже принято именовать поля классов таким способом.

Интересная особенность идентификаторов D их интернациональность: «буква» в определении выше это не только буква латинского алфавита (от A до Z и от a до z), но и знак из универсального набора1, определенного в стандарте C992.

Например, abc, α5, _, Γ_1, _AbC, Ab9C и _9x допустимые идентификаторы, а 9abc и __abc нет.

Если перед идентификатором стоит точка (.какЗдесь), то компилятор ищет его в пространстве имен модуля, а не в текущем лексически близком пространстве имен. Этот префиксный оператор-точка имеет тот же приоритет, что и обычный идентификатор.

В начало ⮍ Наверх ⮍

2.1.1. Ключевые слова

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

Таблица 2.2. Ключевые слова языка D

abstract      else         macro        switch
alias         enum         mixin        synchronized
align         export       module
asm           extern                    template
assert                     new          this
auto          false        nothrow      throw
              final        null         true
body          finally                   try
bool          float        out          typeid
break         for          override     typeof
byte          foreach
              function     package      ubyte
case                       pragma       uint
cast          goto         private      ulong
catch                      protected    union
char          ifIf         public       unittest
class         immutable    pure         ushort
const         import
continue      in           real         version
              inout        ref          void
dchar         int          return
debug         interface                 wchar
default       invariant    scope        while
delegate      isIs         short        with
deprecated                 static
do            long         struct
double        lazy         super

Некоторые из ключевых слов распознаются как первичные выражения. Например, ключевое слово this внутри определения метода означает текущий объект, а ключевое слово super как статически, так и динамически заставляет компилятор обратиться к классу-родителю текущего класса (см. главу 6). Идентификатор $ разрешен только внутри индексного выражения или выражения получения среза и обозначает длину индексируемого массива. Идентификатор null обозначает пустой объект, массив или указатель.

Первичное выражение typeid(T) возвращает информацию о типе T (за дополнительной информацией обращайтесь к документации для вашей реализации компилятора).

В начало ⮍ Наверх ⮍

2.2. Литералы

2.2.1. Логические литералы

Логические (булевы) литералы это true («истина») и false («ложь»).

В начало ⮍ Наверх ⮍

2.2.2. Целые литералы

D работает с десятичными, восьмеричными3, шестнадцатеричными и двоичными целыми литералами. Десятичная константа - это последовательность цифр, возможно, с суффиксом L, U, u, LU, Lu, UL или ul. Вывод о типе десятичного литерала делается исходя из следующих правил:

  • нет суффикса: если значение «помещается» в int, то int, иначе long;
  • только U/u: если значение «помещается» в uint, то uint, иначе ulong.
  • только L: тип константы - long.
  • U/u и L совместно: тип константы - ulong.

Например:

auto
    a = 42,             // a имеет тип int
    b = 42u,            // b имеет тип uint
    c = 42UL,           // c имеет тип ulong
    d = 4_000_000_000,  // long; в int не поместится
    e = 4_000_000_000u, // uint; в uint не поместится
    f = 5_000_000_000u; // ulong; в uint не поместится

Вы можете свободно вставлять в числа знаки подчеркивания (только не ставьте их в начало, иначе вы на самом деле создадите идентификатор). Знаки подчеркивания помогают сделать большое число более наглядным:

auto targetSalary = 15_000_000;

Чтобы написать шестнадцатеричное число, используйте префикс 0x или 0X, за которым следует последовательность знаков 09, af, AF или _. Двоичный литерал создается с помощью префикса 0b или 0B, за которым идет последовательность из 0, 1 и тех же знаков подчеркивания. Как и у десятичных чисел, у всех этих литералов может быть суффикс. Правила, с помощью которых их типы определяются по контексту, идентичны правилам для десятичных чисел.

Рисунок 2.1, заменяющий 1024 слова, кратко и точно определяет синтаксис целых литералов. Правила интерпретации автомата таковы: 1) каждое ребро «поглощает» знаки, соответствующие его ребру, 2) автомат пытается «расходовать» как можно больше знаков из входной последовательности4. Достижение конечного состояния (двойной кружок) означает, что число успешно распознано.

image-2-1

Рис. 2.1. Распознавание целых литералов в языке D. Автомат пытается сделать ряд последовательных шагов (поглощая знаки, соответствующие данному ребру), пока не остановится. Останов в конечном состоянии (двойной кружок) означает, что число успешно распознано. s обозначает суффикс вида U|u|L|UL|uL|Lu|LU

В начало ⮍ Наверх ⮍


  1. Впрочем, использование нелатинских букв является дурным тоном. Прим. науч. ред. ↩︎

  2. С99 обновленная спецификация C, в том числе добавляющая поддержку знаков Юникода. Прим. пер. ↩︎

  3. Сам язык не поддерживает восьмеричные литералы, но поскольку они присутствуют в некоторых C-подобных языках, в стандартную библиотеку был добавлен соответствующий шаблон. Теперь запись std.conv.octal!777 аналогична записи 0777 в C. Прим. науч. ред. ↩︎

  4. Для тех, кто готов воспринимать теорию: автоматы на рис. 2.1 и 2.2 это детерминированные конечные автоматы (ДКА). ↩︎