Приведение типа
Приведе́ние ти́па (type conversion) — преобразование значения переменной одного типа в значение другого типа. Выделяют явное и неявное приведения типов.
- При явном приведении указывается тип переменной, к которому необходимо преобразовать исходную переменную.
- При неявном приведении преобразование происходит автоматически, по правилам, заложенным в данном языке программирования.
- Также в языке могут быть заданы специальные функции для приведения
Неявное приведение типа
Само приведение происходит как во время присваивания значения переменной, так и при операциях сравнения, вычисления выражения. При использовании в выражении несколько различных типов значения одного или нескольких подтипов может быть осуществлено преобразование к более общему типу (супертипу), с большим диапазоном возможных значений.
В языке Си:
double d; // вещественный тип
long l; // целый тип
int i; // целый тип
if (d > i) d = i;
if (i > l) l = i;
if (d == l) d *= 2;
Каждый раз при выполнени операции сравнения или присваивания переменные разных типов будут приведены к единому типу. Следует с осторожностью использовать неявное приведение типа. При переводе числа из вещественного типа в целочисленный, дробная часть откидывается. Обратное приведение из целочисленного типа к вещественному также может привести к понижению точности, что связано с различным представлением вещественных и целочисленных чисел на машинном уровне. К примеру, вещественный тип single стандарта IEEE 754 не может точно представить число 16777217, в то время как 32-битный целочисленный тип может. Это может привести к ситуациям, когда сравнение на равенство одного и того же числа, представленного типами (int и single) будет выдавать ложный результат (числа не равны друг другу).
Явное приведение типа
В языке C
Для явного приведения типов некоторой переменной перед ней следует указать в круглых скобках имя нового типа, например:
int X; int Y = 200; char C = 30; X = (int)C * 10 + Y;//переменная С приведена к типу int.
Если бы в этом примере не было выполнено явное приведение типов, то компилятор предположил бы, что выражение С * 10 + У переменной Х было бы присвоено значение 640, а не корректное 3200. В результате приведения типа переменная С распознается компилятором как 16-ти разрядная, и описанной выше ошибки не возникает.
В языке C++
В языке C++ существует четыре разновидности приведения типа. Все четыре типа записываются в виде
xxx_cast<type_to>(expression_from).
Например:
y = static_cast<signed short>(65534); // будет присвоено -2
Громоздкие ключевые слова являются напоминанием программисту, что приведение типа чревато проблемами.
static_cast
- Назначение: Приведение типа по обычным правилам, когда компилятор отказывается привести его автоматически (отличается от применяемого в Си
(type_to)expression_from
только тем, что с указателями не работает; для указателей применяетсяreinterpret_cast
). Применяется:- для числовых типов;
- для указателей и ссылок при конвертации в родительский тип;
- для типов с конструкторами или операциями конвертации наподобие
operator type_to
; - в шаблонах — компилятор уже при специализации шаблона решает, какие операции использовать;
- в операции
?:
, у которой then- и else-части должны иметь один тип.
- Ограничения на
expression_from
: нет. - Ограничения на
type_to
: должен найтись способ преобразования вtype_to
. - Производит ли код: в общем случае да.
- Возможные ошибки: относительно безопасно. Логические ошибки возможны, если привести в неправильный тип или вообще пропустить приведение, когда оно требуется. Не исключено, что после преобразования появится временный объект, который будет благополучно уничтожен вместе со всеми изменениями.
// Возвращает процент попаданий.
double hitpercent(const int aHitCount, const int aShotCount)
{
if (aShotCount==0) return 0.0;
// Нам нужно дробное деление, а не целочисленное - поэтому переведём делимое и делитель в double
return static_cast<double>(aHitCount*100) / static_cast<double>(aShotCount);
}
string s = static_cast<string>("qqq"); // аналогично string s = string("qqq");
string s = (string)"qqq"; // синтаксис Си тоже работает
string s = static_cast<string>(5); // не компилируется - нет подходящего конструктора
- Назначение: Проводит преобразование типа, предварительно убедившись (с помощью RTTI), что объект
expression_from
в действительности является объектом типаtype_to
. Если нет: для указателей возвращает NULL, для ссылок устанавливает аварийную ситуациюstd::bad_cast
. - Ограничения на
expression_from
: выражение должно быть ссылкой или указателем на объект с хотя бы одной виртуальной функцией. - Ограничения на
type_to
: ссылка или указатель на дочерний по отношению кexpression_from
тип. - Производит ли код: да.
- Возможные ошибки: относительно безопасно. Логические ошибки возможны, если подать аргумент, не имеющий тип
type_to
, в то время как код не приспособлен к этому.
const_cast
- Назначение: Снятие/установка модификатора
const
илиvolatile
. - Ограничения на
expression_from
: ссылка или указатель. - Ограничения на
type_to
: должен совпадать с типомexpression_from
с точностью до модификаторовconst
илиvolatile
. - Производит ли код: нет.
- Возможные ошибки: чревато попыткой изменить неизменный объект.
namespace
{
// Каждая загрузка DLL создаёт новый сегмент данных.
// Так что с такими глобальными переменными одна программа не будет
// мешать другой.
string s = "Wikipedia";
}
typedef char* PChar;
// Функция экспортируется DLL'ем и возвращает какую-то строку
// в виде char*. Проблема в том, что std::string::c_str() возвращает
// const char*.
void __declspec(dllexport) WINAPI SomeDllFunction(PChar& rMessage)
{
rMessage = const_cast<char*>(s.c_str());
}
reinterpret_cast
- Назначение: Участок памяти рассматривается как объект другого типа.
- Ограничения на
expression_from
: интегральный тип (логические, символьные, целые типы), указатель. - Ограничения на
type_to
: интегральный тип (логические, символьные, целые типы), указатель. - Производит ли код: нет.
- Возможные ошибки: Участок в реальности может и не иметь этого типа. Нет никакой возможности проверить это, всю ответственность за корректность преобразования программист берёт на себя.
// Возвращает true, если число конечное, и false - если бесконечное или NaN.
// Работает на 32- и 64-битном IBM PC.
bool isfinite(const double x)
{
const long long& y = reinterpret_cast<const long long&>(x);
return ((y & 0x7FF0000000000000LL) != 0x7FF0000000000000LL);
}
// Ошибка - выражение x+5.0 не является ссылкой.
const long long& y = reinterpret_cast<const long long&>(x+5.0);
В другом языковом разделе есть более полная статья Type conversion (англ.) Вы можете помочь проекту, дописав эту статью с помощью перевода.
|
da:Konvertering (teknik) de:Typumwandlung en:Type conversion es:Conversión de tipos fr:Conversion de type it:Conversione di tipo ja:型変換 ko:형변환 nl:Typeconversie pl:Konwersja typu
Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....