Подтвердить что ты не робот

Что такое тип в C/С++?

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

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

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

Как компилятор знает (или программиста), если я могу наложить, например. FOO to BAR?

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

Просто хочу упомянуть что-то часто забытое:

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

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

#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));
}

Это делает LOOKS бесполезным. Но внешний вид может обманывать.

Ответ 3

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

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