Приведение типа

Материал из Seo Wiki - Поисковая Оптимизация и Программирование

Перейти к: навигация, поиск

Приведе́ние ти́па (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); // не компилируется - нет подходящего конструктора
dynamic cast
  • Назначение: Проводит преобразование типа, предварительно убедившись (с помощью 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);


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

Личные инструменты

Served in 0.151 secs.