Преобразование типов в C и C++
Преобразовывать одни типы в другие в основном не рекомендуется из-за того, что возможна ненамеренная утеря данных и появление ошибок и предупреждений в процессе компиляции программы. Однако для решения некоторых задач данная операция необходима.
Для начала стоит сказать, существует явное и неявное приведение типов. Явные осуществляются непосредственно программистом с помощью операторов или конвертации, а неявные — компилятором.
Конвертация C-style
Данное приведение осуществляется с помощью оператора (…), внутри которого пишется тип, в который нужно конвертировать.
Пример:
int Ts_1 = 127;
int Ts_2 = 3;
char Ts_3 = (char)Ts_1 / Ts_2; // явное преобразование
cout << Ts_3 << endl;
Даны две переменные типа int и одна типа char. Если Ts_3 была такого же типа, что и Ts_1 с Ts_2, то на экране появилось бы целое число, равное 42:
Пример:
int Ts_1 = 127;
int Ts_2 = 3;
int Ts_3 = Ts_1 / Ts_2;
cout << Ts_3 << endl;
Но из-за того, что переменная Ts_3 имеет тип char (см. пример 1) и используется конвертация C-style, на выходе будет получена строка с символом » * «.
Пример:
int Ts_a = 200;
char Ts_b = 30;
int Ts_c = (int)Ts_b * 10 + Ts_a; // явное приведение Ts_b
cout << Ts_c << endl;
Здесь переменная Ts_b приводится к целочисленному типу путём расширения разрядности. Без оператора (int) переменная Ts_c так же равнялась бы 500, однако уже имело бы место неявное преобразование типов.
Операция static_cast
Оператор удобно использовать при конвертации переменной типа char в int. Он осуществляет явное допустимое приведение типа данных.
Пример:
char Ts_4(113);
cout << Ts_4 << endl; // на выходе будет получен символ » q »
cout << static_cast<int>(Ts_4) << endl; // явное преобразование
Как видно, данный оператор позволяет «превращать» символы в числа. Стоит помнить, что диапазоны значений у char и int сильно разняться, из-за чего присвоенное значение может отличаться от того, что будет выведено на экране.
Пример:
char Ts_4(300);
cout << Ts_4 << endl; // символ » , »
cout << static_cast<int>(Ts_4) << endl; // 44
Тип char включает в себя целочисленные значения от 0 до 255 включительно. При присвоении char значения большего 255 отсчёт начинается заново, то есть с нуля. При char Ts_4(256) оператор static_cast позволил бы получить число 0. До значения, которое было присвоено Ts_4 в примере 5, осталось 44 единицы, поэтому в третьей строчке и выдаётся это число.
Указатели и преобразование
Указатели тоже можно преобразовывать по типам. Однако такое приведение во многом более проблемно порой из-за невнимательности при записи кода или непонимания, как вообще работают указатели.
Пример:
int Ts_5(42);
int *Ts_6 = &Ts_5;
char *Ts_7 = (char*)Ts_6;
cout << *Ts_7 << endl;
В программе объявлена и инициализирована целочисленная переменная Ts_5. На следующей строке находиться указатель на переменную Ts_5, то есть присвоение адреса переменной указателю. Третья строка — назначение указателю в левой части char *Ts_7 той же области памяти, что и в правой части (char*)Ts_6. На выходе будет получена строка с символом » * «.
Стоит заметить, что такая запись третьей строки char *Ts_7 = (char)*Ts_6; будет являться ошибкой синтаксиса, так как указатель (звёздочка *) должен быть связан не с переменной Ts_6, а с типом этой переменной, то есть с char.
Опасные неявные преобразования
Пример:
int Ts_8(13);
char Ts_char(Ts_8);
Такое преобразование небезопасно, так как в процессе компиляции будет происходит преобразование 4 байт типа int информации в 1 байт типа char. Иными словами, происходит ненамеренная утеря информации. Поэтому лучше пользоваться явным приведением, например, применять оператор static_cast.