; /* ничего не делает */
Составные операторы, или блоки, состоят из одного или большего количества операторов (которые сами могут быть составными операторами), заключенных в фигурные скобки. Приведенный ниже пример оператора while содержит составной оператор:
while (years < 100)
{
wisdom = wisdom * 1.05;
printf("%d %d\n", years, wisdom);
years = years + 1;
}
Преобразования типов
Операторы и выражения обычно должны использовать одни и те же типы выражений и констант. Однако если вы смешиваете типы, то язык С этому не препятствует, как это делает, скажем, Pascal. Взамен применяется набор правил, обеспечивающих автоматическое преобразование типов данных. Это может быть удобным, но также и опасным, особенно если смешивание типов происходит неумышленно. (Программа lint, входящая в состав многих систем Unix, проверяет наличие “конфликтов” между типами. Многие компиляторы С, которые ориентированы на системы, отличные от Unix, информируют о возможных проблемах с типами, если выбран высокий уровень сообщений об ошибках.) Неплохо иметь хотя бы общее представление о правилах преобразования типов.
Ниже описаны базовые правила преобразования типов данных.
1. Находясь в выражении, типы char и short (как signed, так и unsigned) автоматически преобразуются в int или при необходимости в unsigned int. (Если тип short имеет такой же размер, как у int, то размер типа unsigned short больше, чем int; в этом случае unsigned short преобразуется в unsigned int.) В K&R С, но не в текущей версии языка тип float автоматически преобразует-
Операции, выражения и операторы 185
ся в double. Поскольку они являются преобразованиями в большие по размеру типы, они называются повышением.
2. Если в любую операцию вовлечены два типа, оба значения приводятся к более высокому из этих двух типов.
3. Порядок типов от высшего к низшему выглядит так: long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int и int. Возможно одно исключение, когда long и int имеют одинаковые размеры; в этом случае unsigned int nревосходит long. Типы short и char в этом списке отсутствуют, т.к. они уже должны были повыситься до int или, возможно, до unsigned int.
4. В операторе присваивания финальный результат вычислений преобразуется к типу переменной, которой присваивается значение. Процесс может привести к повышению типа, как описано в правиле 1, или к понижению типа, при котором значение преобразуется в более низкий тип.
5. При передаче в качестве аргументов функции типы char и short преобразуются в int, a float — в double. Это автоматическое повышение переопределяется прототипированием функций, как будет показано в главе 9.
Повышение обычно представляет собой гладкий процесс без особых происшествий, но понижение может привести к реальной проблеме. Причина проста: типа более низкого уровня может оказаться недостаточно для сохранения полного числа. Например, 8-битная переменная char может хранить целочисленное значение 101, по не 22334. Что происходит, когда преобразованное значение не умещается в целевой тип? Ответ зависит от задействованных типов. Ниже приведены правила для случаев, когда присвоенное значение не помещается в конечном типе.
1. Когда целевым является одна из форм целочисленного типа без знака, а присвоенное значение представляет собой целое число, лишние биты, делающие значение слишком большим, игнорируются. Например, если целевой тип — 8-битный unsigned char, то присвоенным значением будет результат деления исходного значения по модулю 256.
2. Если целевым типом является целый тип со знаком, а присвоенное значение — целое число, то результат зависит от реализации.
3. Если целевой тип является целочисленным, а присвоенное значение представляет собой значение с плавающей запятой, то поведение не определено.
А что, если значение с плавающей запятой умещается в целочисленный тип? Когда типы с плавающей запятой понижаются до целочисленного типа, они усекаются или округляются в направлении нуля. Это означает, что и 23.12, и 23.99 усекаются до 23, а -23.5 усекается до -23.
В листинге 5.14 иллюстрируется работа некоторых из описанных правил.
Листинг 5.14. Программа convert.с

186 Глава 5

В результате выполнения программы convert.с получается следующий вывод:
ch = С, i = 67, fl = 67.00
ch = D, i = 203, fl = 339.00
Теперь ch = S
Теперь ch = P
Вот что происходит в системе, в которой реализованы 8-битный тип char и 32битный тип int.
Читать дальше