Что именно является приведением типа в C / C ++? - PullRequest
39 голосов
/ 26 сентября 2011

Что такое приведение типов в C / C ++? Как компилятор проверяет, нужна ли (и допустима ли) явная трансляция типов? Сравнивает ли это пространство, необходимое для значения? Если у меня есть например:

int a;
double b = 15.0;
a = (int) b;

Если я правильно помню, двойное значение требует больше места (было ли это 8 байт ?!), чем целое число (4 байта). И внутреннее представление обоих совершенно разное (дополнение на два / мантисса). Так что же происходит внутри? Пример здесь довольно прост, но в C / C ++ существует множество типов типов.

Как компилятор узнает (или программист), могу ли я привести, например. ФУ БАР?

Ответы [ 4 ]

31 голосов
/ 26 сентября 2011

Приведение типов - это, по сути, преобразование одного типа в другой. Он может быть неявным (т. Е. Выполненным автоматически компилятором, возможно, теряющим информацию в процессе) или явным (т. Е. Указанным разработчиком в коде). Пространство, занимаемое типами, имеет второстепенное значение. Более важным является применимость (а иногда и удобство) конвертации.

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

Для преобразований, которые могут быть совершенно опасными (например, из базы в производный тип), стандарт C ++ требует явного приведения. Кроме того, он предлагает более ограниченные явные приведения, такие как static_cast, dynamic_cast, reinterpret_cast и const_cast, каждое из которых дополнительно ограничивает явное приведение только подмножеством возможных преобразований, уменьшая потенциальные за ошибки приведения.

Допустимые преобразования, как неявные, так и явные, в конечном итоге определяются стандартами C / C ++, хотя в C ++ разработчик имеет возможность расширять преобразования для пользовательских типов, как неявных, так и явных, с использованием конструкторов и перегруженных ( операторы.

Полные правила, для которых приведение стандартов разрешено, а какие нет, могут стать довольно запутанными. Я постарался правдиво представить несколько кратких резюме некоторых из этих правил в этом ответе. Если вы действительно заинтересованы в том, что разрешено и запрещено, я настоятельно призываю вас ознакомиться со стандартами и прочитать соответствующие разделы о преобразовании типов.

9 голосов
/ 26 сентября 2011

Просто хочу упомянуть что-то, что часто упускается из виду:

  • При приведении всегда создается временный объект целевого типа (хотя, если целевой тип является ссылкой, вы не заметите).

Это может быть важно.Например:

#include <iostream>

void change_one_print_other( int& a, const int& b )
{
    a = 0;
    std::cout << b << "\n";
}

int main(void)
{
    int x = 5, y = 5;

    change_one_print_other(x, x);
    change_one_print_other(y, static_cast<int>(y));
}

Это бросает взгляды бесполезно.Но внешность может быть обманчива .

1 голос
/ 26 сентября 2011

Создайте небольшую C-программу из своего кода и следуйте инструкциям в Как заставить GCC генерировать код сборки , чтобы увидеть, как компилятор выполняет приведение типов.

1 голос
/ 26 сентября 2011

Есть определенные типы приведений, которые компилятор знает, как делать неявно - double to int является одним из них. Это просто отбрасывает десятичную часть. Внутреннее представление преобразуется как часть процесса, поэтому назначение работает правильно.

Обратите внимание, что значения слишком велики для правильного преобразования. Я не помню, каковы правила для этого случая; он может быть оставлен на усмотрение компилятора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...