Материал: lectures_3

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

целочисленный тип. Результат выполнения рассматриваемого оператора, если один из операторов отрицателен, зависит от реализации.

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

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

бинарных операторов

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

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

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

Явное.

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

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

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

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

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

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

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

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

char,

signed char,

31

unsigned char,

short,

unsigned short.

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

#include<stdio.h>

#include<conio.h> int main(void)

{

short n = 5; char ch = ‘A’;

printf(“n + ch = %d sizeof(n + ch)=\n”, n + ch, sizeof(n + ch));

getch(); return 0;

}

В вызове функции 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,

32

● int.

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

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

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

Явное преобразование типа основано на применении оператора приведения типов. Общий вид применения оператора приведения типа имеет

следующий вид:

(тип ) выражение

Здесь тип – это любой тип, который поддерживается языком Си. Например, следующая запись позволяет преобразовать значение выражения x * y / 5 к типу float:

(float) (x * y / 5)

В отличие от автоматических явные преобразования типов могут быть как безопасными, так и опасными.

Оператор приведения типа является унарным оператором и имеет тот же приоритет, что и другие унарные операторы.

15.4.Математические функции

При написании арифметических выражений часто приходиться использовать стандартные математические функции, прототипы которых находятся в заголовочном файле math.h. Вызов функции состоит из ее имени и заключенного в круглые скобки списка фактических параметров. В качестве фактического параметра математических функций можно использовать арифметическое выражение. Ниже в таблице приведены прототипы некоторых математических функций.

Имя

Прототип

Описание

 

 

 

функции

int abs(int num);

 

 

 

 

abs

Вычисление модуля аргумента num

ceil

double ceil(double num);

Возвращает

наименьшее

целое,

 

 

которое

удовлетворяет

условию

 

 

>= num. Обратите внимание на тип

 

double cos(double num);

возвращаемого значения (double).

cos

Вычисляет

значение косинуса от

 

 

аргумента

num.

Значение

аргумента

 

double fabs(double num);

должно быть задано в радианах.

fabs

Вычисление

значение

модуля

 

double floor(double num);

аргумента num

 

 

floor

Возвращает

наибольшее

целое,

33

 

 

которое удовлетворяет

условию

 

 

double exp(double num)

<= num.

 

 

 

 

exp

Вычисляет

значение

экспоненты

от

 

double log(double num);

аргумента num

 

 

 

log

Вычисляет

значение

натурального

 

double log10(double num);

логарифма от аргумента num.

 

log10

Вычисляет

значение

логарифма

по

 

double pow(double base,

основанию 10 от аргумента num.

 

pow

Вычисляет

значение аргумента base,

 

double x);

возведенное в степень x.

 

 

sin

double sin(double num);

Вычисляет

значение

синуса

от

 

 

аргумента

num. Значение

аргумента

 

double sqrt(double num);

должно быть задано в радианах.

 

sqrt

Вычисляет

значение

корня

 

double tan(double num);

квадратного от аргумента num.

 

tan

Вычисляет

значение

тангенса

от

 

 

аргумента

num. Значение

аргумента

 

 

должно быть задано в радианах.

 

16.Оператор присваивания и инструкция присваивания

Вязыке Си различают две формы оператора присваивания:

простой оператор присваивания,

составной оператор присваивания.

Составной оператор отличается наличием дополнительной операции, которая выполняется до присваивания. Рассмотрим вначале простой оператор присваивания.

Любой оператор присваивания, не входящий в состав другого выражения, может выступать в качестве инструкции присваивания, если после него поставить точку с запятой. Например, n = 5 – это оператор присваивания, а n = 5; - это инструкция присваивания.

16.1.Простой оператор присваивания

Основное назначение оператора присваивания в языках программирования состоит в выполнении следующих операций:

в запоминании в памяти входных данных и результатов вычислений некоторых выражений.

в перемещении данных из одной области памяти в другую.

Вязыке Си присваивание имеет расширенное по сравнению с другими языками (Паскаль и Бейсик) назначение. Дело в том, что в языке Си может использоваться возвращаемое оператором присваивания значение. Это связано с тем обстоятельством, что присваивание в языке Си относится к категории операторов (operator), а не инструкций (statement), как это имеет место в других языках. Приведем пример, в котором используется значение, возвращаемое оператором присваивания.

#include<stdio.h>

#include<conio.h>

34

int main(void)

{

int x = 10; int y = 20;

printf("%d\n", x = y); /* ... */

getch(); return 0;

}

Вэтом программном коде вызов функции printf() используется для вывода на дисплей результата выполнения оператора присваивания.

Оператор присваивания относится к категории бинарных операторов. В качестве знака присваивания в языке Си используется математический знак равенства “=”. При выполнении оператора присваивания вначале вычисляется его правый операнд, затем вычисленное значение записывается

вобласть памяти, адрес которой определяется его левым операндом. Требование знания адреса накладывает ограничения на выражение, которое может использоваться в качестве левого операнда присваивания. К левому операнду должна быть допустима операция взятия адреса. Выражения, допускающие применение этой операции, принято называть lvalue выражениями. Различают две категории lvalue выражений:

изменяемые,

неизменяемые.

Вкачестве левого операнда присваивания следует применять модифицируемое lvalue выражение.

Возвращаемым значением оператора присваивания является значение, записанное в его левый операнд. В книгах по языку Си и в сообщениях компилятора за левым операндом оператора присваивания закрепился термин lvalue (left side value), а за правым - rvalue (right side value) Таким образом, в общем случае простой оператор присваивания имеет следующий формат:

модифицируемое_lvalue_выражение = rvalue_выражение

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

Приведем примеры операторов присваивания. Пусть x и y – переменные, имеющие тип double. Тогда допустимы следующие операторы присваивания.

x = 4.5 y = x - 3

35

Источник: https://studfile.net/preview/16544272/