Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_по_пяву_4.doc
Скачиваний:
101
Добавлен:
15.03.2015
Размер:
1.29 Mб
Скачать
    1. Бинарные операторы

Перейдем к рассмотрению бинарных арифметических операторов. Операторы “+” (сложить), “-” (вычесть), “*” (умножить) имеют обычный арифметический смысл. При использовании бинарных операторов в языке Си допускается использование операндов, имеющих разные арифметические типы. При этом компилятор выполняет автоматическое преобразование типа. Следует учитывать особенность, имеющую место в языке Си, при выполнении операции деления (оператор /) для данных целого типа. Результат выполнения операции деления в этом случае имеет целый тип. Стандарт языка Си строго определяет эту операцию только для случая, когда оба операнда положительны. В этом случае дробная часть отбрасывается. В том случае, когда только один операнд отрицателен, результат зависит от реализации. Приведем пример. Рассмотрим результаты выполнения следующего вызова функции printf()

printf(“23 / 4 = %d-23 / 4= %d\n”, 23 / 4, -23 / 4);

При выполнении программы, содержащий этот вызов функции, в среде Builderv. 6 был получены следующие результаты:

23 / 4= 5 -23 / 4= - 5.

Отметим, что при выполнении в другой среде при вычислении выражения -23 / 4 может быть получено число -6.

Бинарный оператор “%” выполняет вычисление остатка от деления левого операнда на правый операнд. Каждый из операндов может иметь любой целочисленный тип. Результат выполнения рассматриваемого оператора, если один из операторов отрицателен, зависит от реализации.

Бинарные операторы “ – ” и “+” имеют одинаковый приоритет, который ниже приоритета операторов “*”, “/” и “%”. Приоритет унарных операторов выше приоритета бинарных операторов. Унарные операторы имеют правую ассоциативность, а бинарные операнды – левую ассоциативность.

    1. Преобразования типа при выполнении бинарных операторов

Вычислять значение выражения можно только в том случае, если его операнды имеют одинаковые типы. Компилятор сильно типизированного языка должен “отказываться” обрабатывать выражения, операнды которых имеют разные типы. Однако такой подход не всегда является оправданным. Дело в том, что существуют близкие по своему назначению типы. К таким, например, типам относятся арифметические типы. В распоряжение программиста язык Си предоставляет большое количество разновидностей арифметических типов. Представляется целесообразным допускать использование некоторых категорий смешанных выражений, операнды которых имели бы разные, но близкие по своему назначению типы. Такой подход реализован в языке Си.

В языке Си предусмотрена возможность выполнения преобразования типов при вычислении смешанных арифметических выражений. Назначение преобразования типа состоит в том, чтобы привести операнды к одному общему типу. Язык предусматривает две разновидности преобразования типов;

● Неявное (автоматическое).

● Явное.

Остановимся вначале на автоматическом преобразовании типов.

Автоматическое преобразование типов

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

При выполнении автоматических преобразований типов все арифметические типы разделены на две категории:

● Короткие типы

● Длинные типы.

В основу этой классификации положен размер памяти, которую занимают данные.

К коротким типам относятся следующие типы:

char,

signed char,

unsigned char,

short,

unsigned short.

Для всех коротких типов при преобразованиях типов вначале выполняется операция, которая называется целочисленным повышением: все короткие типы преобразуются к типу int. Для этого правила имеется одно уточнение. Типunsigned short преобразуется в тип int только в том случае, когда этот тип (int) достаточен для представления всего диапазона значений типаunsigned short (обычно это имеет место в тех системах, где для представления данных типаshortотводится половина машинного слова и полное слово – для данных типа int). В последнем случае типunsigned short преобразуется в unsigned int. Рассмотрим программный код, приведенный ниже:

#include<stdio.h> #include<conio.h>

intmain(void) {shortn = 5;charch = ‘A’; printf(“n + ch = %d sizeof(n + ch)=\n”, n + ch, sizeof(n + ch)); getch();return0; }

В вызове функции printf() вычисляется значение выражения n + ch и размер памяти, который занимает результат вычисления этого значения. При выполнении этой программы в среде Builder v . 6 на экране дисплея получен следующий результат:

n + ch = 70 sizeof(n + ch)=4

Значение переменной ch, преобразованное к типу int, будет равно 65. Сложение этого числа со значением переменной n и дает в качестве результата вычисления выражения n + ch число 70. Завершающая часть вывода (sizeof(n + ch) = 4) может рассматриваться как доказательство того положения, что вычисления действительно выполнялись с операндами, преобразованными к типуint.

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

long double,

double,

float,

unsigned long long,

long long,

unsigned long,

long,

unsigned,

int.

При использовании в выражении операндов, имеющих разные ранги, тип операнда, имеющий меньший ранг, приводится к типу операнда, имеющего больший ранг. Например, если в выражении один операнд имеет тип double, а второй –long, то тип второго операнда должен быть преобразован к типуdouble.

Из этого правила существует одно исключение. Если один из операндов имеет тип long, а второй -unsigned, причем не все значенияunsigned intмогут быть представлены типомlong, то оба операнда преобразуются к типуunsigned long.