Неявное приведение типов

Приведение типов происходит автоматически, если в некотором месте исходного кода используется один тип, но ожидается другой, и существуют правила конвертации между ними. Такое приведение называется неявным и может не всегда отвечать замыслу программиста. Кроме того, некоторые операции конверсии имеют побочные эффекты, и компилятор, не зная, является ли их применение намеренным, выделяет соответствующие строки кода предупреждениями. Для решения этих проблем существует синтаксис явного приведения типов (см. далее Явное приведение типов).

Некоторые из правил неявного приведения типов мы уже встречали при изучении типов и переменных.

В частности, если значение типа, отличного от логического, присваивается переменной bool, то значение 0 расценивается как false, а всё остальное — как true. В более общем случае, все выражения, которые предполагают наличие логических условий, приводятся к типу bool. Например, первый операнд тернарного условного оператора всегда конвертируется в bool.

Если же значение типа bool присваивается числовому типу, то true становится равно 1, а false — 0.

Когда вещественное число присваивается переменной целого типа, дробная часть отбрасывается (компилятор выдает предупреждение). Когда целое число, наоборот, присваивается переменной вещественного типа, возможна потеря точности (компилятор также выдает предупреждение). Об этом мы уже говорили в разделах про Целые числа и Вещественные числа.

При наличии целых чисел и чисел с плавающей запятой, всё приводится к числам с плавающей запятой максимального использованного размера (обычно double, если нет явного указания float или в числовом литерале не стоит суффикс 'f', например — 1234.56789f).

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

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

Учитывая вышеизложенное, в одной строке кода может выполняться большое количество преобразований. Если при этом возникают предупреждения компилятора, желательно убедиться, что конвертация сделана намеренно, и ликвидировать предупреждения, вставив явное приведение типов.

short s = 10;
long n = 10;
int p = s * n + 1.0;

В этом примере при выполнении умножения тип переменной s расширяется до типа второго операнда long и получается промежуточный результат типа long. Поскольку константа 1.0 имеет тип double, результат произведения конвертируется перед сложением в double. Общий результат также имеет тип double, однако переменная p имеет тип int, и потому выполняется неявное приведение типа из double в int.

Специальные типы datetime и color обрабатываются по правилам целых длиной 8 и 4 байта соответственно. Но для даты и времени существует более строгое ограничение на максимальную величину — 32535244799, что соответствует D'3000.12.31 23:59:59'.

Большинство типов может неявно конвертироваться в строки и обратно, но результаты не всегда адекватны, поэтому компилятор выдает предупреждения "неявное преобразование числа в строку" и "неявное преобразование строки в число" ("implicit conversion from 'number' to 'string'", "implicit conversion from 'string' to 'number'"), чтобы программист их проверил. Например, преобразование строки в целое число допускает наличие в строке только цифр и знаков '+'/'-' в начале. Конвертация из строки в вещественное — разрешает помимо цифр наличие точки '.' и формы записи с "экспонентой" ('e' или 'E', например, +1.2345e-1). Если в строке встретится посторонний символ (например, буква), весь остаток строки отбрасывается.

Например, дату и время в виде строки ("2021.12.12 00:00") не удастся без потерь присвоить переменной типа datetime, поскольку datetime — это целое число (количество секунд). И чтение числа из строки завершится по достижении первой точки, то есть число получит значение 2021. Это количество секунд соответствует 34-й минуте 1970-го года.

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

Единственное направление неявного и явного приведения типов, которое запрещено, это из string в bool. Компилятор в таких случаях выдает ошибку "нельзя неявно преобразовать 'string' в 'bool'" ("cannot implicitly convert type 'string' to 'bool'").

Примеры из данной главы можно найти в скрипте TypeConversion.mq5.