Преобразование типов

Ввиду статической типизации, записать число одного типа в переменную другого типа напрямую невозможно, необходимо приведение. В некоторых случаях приведение происходит автоматически: если операнды некоторой операции имеют разные типы, то они преобразуются из «узких» (которые занимают меньше места в памяти) к более «широким» без потери данных.

int a   = 1;
float b = 2.0f;
float c = b + a; // a converts to float

Символьная переменная char представляет собой число.

char letter = 'A'; // 'A' is 65 in ASCII

Стандарт при этом ничего не говорит о том, является ли char беззнаковым, и в зависимости от компилятора реализация может быть разной. Для стандартной части ASCII (первые 127 символов) гарантируется, что при преобразовании из char в int результатом будет положительное число, а вот расширение ASCII на разных системах может дать как положительное, так и отрицательное. Если требуется хранить информацию не символьного характера, то имеет смысл явно указать знаковость при помощи модификатора.

Преобразования от более «широких» к более «узким» в общем случае происходит с потерей данных.

4 июля 1996 года из Французской Гваины была запущена ракета Arian V, разработка которой заняла 10 лет и стоила Европейскому Союзу порядка 7 млрд. долларов, вместе с полезной нагрузкой стоимостью 500 млн. долларов. На 34-й секунде полёта ракета взорвалась по причине ошибки в программном обеспечении: при попытке сконвертировать 64-битную переменную с плавающей запятой, отвечающую за горизонтальную скорость, в 16-битное число со знаком произошло переполнение регистра (число оказалось больше 32767, т.е. максимально допустимого для 16-битной переменной), что привело к исключительной ситуации и краху всей системы, так как проверка переполнения была отключена. ПО было написано на языке Ада.

uint32_t a = 1023;
uint8_t  b =    a; // b == 255

Большинство компиляторов при подобных преобразованиях выводят предупреждения. И несмотря на это, ошибки, связанные с преобразованием типов, одни из самых распространенных: программист самостоятельно должен отслеживать диапазоны. При преобразовании более «широких» к более «узким» типов лучше всего указывать преобразование явным способом, например так:

#define MM_PER_INCH               25.4f
uint8_t a = (uint8_t)(MM_PER_INCH);

Изменено: