Преобразование типов в 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.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *