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

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

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

Изменено:

Язык Си: 3 комментария

  1. >Вместо нуля может быть почти любой другой символ. Плюс и минус работают по-другому. Для выравнивания числа по по левому краю, а не по правому, перед числом нужно поставить знак минус.
    Лишне по

  2. Термин «регистр ядра» довольно специфичен. Звучит не привычно. А почему не использовать термин CPU или процессор или на худой конец микроконтроллер?

  3. Смысл статических переменных вне функции мне кажется не раскрыт. Такой модификатор делает переменную недоступной из других единиц трансляции. Т.е. не будет конфликта имен между разными .с файлами.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.