Преобразования типов. Лекция 4

Содержание

Слайд 2

План лекции Преобразования Целых и типов с плавающей точкой l-value Массивов

План лекции

Преобразования
Целых и типов с плавающей точкой
l-value
Массивов
Функциональных типов
С типом void
Указателей

Слайд 3

Простая часть Неявные (автоматические) Явные Преобразование в совместимый тип сохраняет значение

Простая часть

Неявные (автоматические)
Явные
Преобразование в совместимый тип сохраняет значение и представление значения
Конец

простой части
Слайд 4

Непростая часть

Непростая часть

Слайд 5

Неявные арифметические преобразования При выполнении операции x op y, кроме операций

Неявные арифметические преобразования

При выполнении операции x op y, кроме операций присваивания

и сдвига, с операндами числовых типов Т1 и Т2, значения выражений х и у преобразуются к типу Т, который удовлетворяет условиям
Есть путь из Т1 в Т
Есть путь из Т2 в Т
Т – наименьший из возможных (если есть путь из Т1 в ТТ и из Т2 в ТТ, то есть путь из Т в ТТ для любого ТТ)
Пунктирная стрелка выбирается, если множество значений нижнего типа ⊆ множество значений верхнего типа; иначе выбирается сплошная стрелка
Переход от битового поля, char, unsigned char, short, unsigned short к int или unsigned int называется целочисленное повышение
Для присваивания и сдвига результат всегда преобразуется к типу левого операнда

char

unsigned char

short

unsigned short

long

unsigned long

int

unsigned int

float

double

long long

unsigned long long

long double

Слайд 6

Преобразования целых Если значение представимо в Т, то преобразование к Т

Преобразования целых

Если значение представимо в Т, то преобразование к Т сохраняет

значение
И может изменить представление
Если Т беззнаковый, то к значению добавляется или вычитается 1 + max(диапазон Т) до тех пор, пока результат не попадет в диапазон Т
Иначе результат преобразования зависит от реализации (implementation-defined)
Например, преобразование может привести к возникновению «исключительной ситуации» (exception)
Слайд 7

Преобразования целых и с плавающей точкой Преобразование конечного числа с плавающей

Преобразования целых и с плавающей точкой

Преобразование конечного числа с плавающей точкой

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

Преобразования для типов с плавающей точкой Преобразования по цепочке float -->

Преобразования для типов с плавающей точкой

Преобразования по цепочке float --> double

--> long double сохраняют значение
Представление может измениться
Преобразование к меньшему типу Т с плавающей точкой
Если значение представимо в Т точно, то оно сохраняется
Если значение попадает в диапазон Т, то выбирается ближайшее меньшее или большее значение Т
Зависит от реализации
Если не попадает в диапазон Т, то поведение не определено
Слайд 9

Преобразования других целых типов Ранг расширенного целого типа ниже ранга стандартного

Преобразования других целых типов

Ранг расширенного целого типа ниже ранга стандартного типа

той же ширины
Соотношение рангов расширенных целых типов одинаковой ширины является implementation-defined
С99: Ранг _Bool ниже ранга любого другого целого типа
Слайд 10

Преобразование l-value в обычное значение 1/2 L-value – это выражение имеющее

Преобразование l-value в обычное значение 1/2

L-value – это выражение имеющее полный

тип или неполный тип, отличный от void, и обозначающее значение в памяти
Изменяемое l-value – это l-value, которое
Не является массивом
Имеет полный тип без квалификатора const
Если это struct или union, то все его элементы (рекурсивно) имеют тип без квалификатора const
Слайд 11

Преобразование l-value в обычное значение 2/2 Если l-value не является массивом

Преобразование l-value в обычное значение 2/2

Если l-value не является массивом и

не является операндом sizeof, унарного &, ++, --, ., оператора присваивания, то оно преобразуется в обычное значение
Тип результата = тип l-value без квалификаторов
Если l-value имеет неполный тип, не является массивом и является операндом, то поведение не определено
Слайд 12

Преобразование массивов Массив типа Т преобразуется в указатель на нулевой элемент

Преобразование массивов

Массив типа Т преобразуется в указатель на нулевой элемент массива
Этот

указатель не является l-value
Кроме массивов, являющихся
Операндом sizeof
Операндом унарного &
Строковым литералом, инициализирующим массив
Слайд 13

Преобразование функциональных типов Именующее выражение функции (function designator) – это выражение,

Преобразование функциональных типов

Именующее выражение функции (function designator) – это выражение, имеющее

функциональный тип
«Функция, возвращающая Т», преобразуется к типу «указатель на функцию, возвращающую Т»
Кроме именующих выражений функции, являющихся
Операндом sizeof
При этом операнду sizeof запрещено иметь функциональный тип
Как вы это понимаете?
Унарного &
Слайд 14

Преобразования типа void Тип void нельзя преобразовывать Любой тип можно преобразовать

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

Тип void нельзя преобразовывать
Любой тип можно преобразовать к void

при этом значение
Вычисляется
Так как вычисление может иметь побочные эффекты
Становится недоступным
Слайд 15

Безопасные преобразования указателей Целое 0 в указатель любого типа Получается нулевой

Безопасные преобразования указателей

Целое 0 в указатель любого типа
Получается нулевой указатель, отличный

от всех остальных указателей
void* в любой Т*
Любой Т* в void*
T* в const T* и volatile T*
Во всех случаях:
Меняется только тип выражения
Значение указателя не меняется
well-defined
Слайд 16

Другие преобразования указателей Целое в указатель Implementation-defined, результат может быть «негодным»

Другие преобразования указателей

Целое в указатель
Implementation-defined, результат может быть «негодным» указателем
Указатель Т*

в целое типа Т1
Implementation-defined, если sizeof(T*) <= sizeof(Т1)
Undefined behavior иначе
Любой Т1* в Т2*
Меняется тип выражения, значение указателя сохраняется
Undefined behavior, если значение указателя не выравнено для типа Т2
Указатель на функцию в указатель на любую другую функцию
Меняется тип выражения, значение указателя сохраняется
Undefined behavior, если при вызове тип именующего выражения функции не совместим с типом вызываемой функции