Главная страница

Алгоритмизации


Скачать 1.15 Mb.
НазваниеАлгоритмизации
Дата27.09.2022
Размер1.15 Mb.
Формат файлаdocx
Имя файла12_100229_1_124427 (1).docx
ТипДокументы
#700459
страница6 из 67
1   2   3   4   5   6   7   8   9   ...   67

ГЛАВА 4. Обзор операций




    1. Операции,выражения


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

Знак операции это один или более символов, определяющих действие над операндами, т.е. операции задают действия, которые необходимо выполнить. Внутри знака операции пробелы не допускаются.

Операции делятся на унарные, бинарные и тернарные – по количеству участвующих в них операндов, и выполняются в соответствии с приоритетами. Для изменения порядка выполнения операций используются круглые скобки.

Большинство операций выполняются слева направо, например, a+b+c

(a+b)+c. Исключение составляют унарные операции, операции присваивания и условная операция (?:), которые выполняются справа налево.

В языке Си используются четыре унарные операции, имеющие самый высокий приоритет, их часто называют первичными:

    • операция доступа к полям структур и объединений при помощи идентификаторов «.» – точка;

    • операция доступа к полям структур и объединений при помощи указателей «–>» – стрелка;

    • операция [ ] индексации, используемая при декларации массива и обращении к его элементам;

    • операция ( ) обращения к функции.

Первичные операции будут рассмотрены в соответствующих разделах.

Полный список операций с указанием их приоритетов приводится в прил. 2.

    1. Арифметическиеоперации


Обозначения арифметических операций:

+ (сложение); – (вычитание); / (деление, для int операндов – с отбрасыванием остатка); * (умножение); % (остаток от деления целочисленных операндов со знаком первого операнда– деление «по модулю»).

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

Порядок выполнения действий в арифметических выражениях следующий: выражения в круглых скобках; операции *, /, %; операции +, –.

Унарные операции «знак числа» (+, –) обладают самым высоким приоритетом и определены для операндов числовых типов (имеющих числовой результат), при этом «+» носит только информационный характер,

«–» меняет знак операнда на противоположный (неадресная операция).

Операции *, /, % обладают высшим приоритетом над операциями +, ,

поэтому при записи сложных выражений нужно использовать общепринятые

математические правила: x

круглые скобки.

a


yz+−↔
x+y*za/(b+с) , т.е. использовать

b+
    1. Операцияприсваивания


Формат операции присваивания:

Операнд_1 = Операнд_2 ;

Операндом_1 (левый операнд) может быть только переменная. Левый операнд операции присваивания получил название L–значение, (Lvalue, Leftvalue) адресное выражение. Так в Си называют любое выражение, адресующее некоторый участок оперативной памяти, в который можно записать некоторое значение. Переменная – это частный случай адресного выражения.

Операндом_2 (правый операнд) могут быть: константа, переменная или любое выражение, составленное в соответствии с синтаксисом языка Си.

Правый операнд операции присваивания назвали R–значение, (R–value,

Right–value).

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

int i, j, k; floatx, y, z;

...

i= j = k= 0; ↔ k= 0, j= k, i = j;

x= i+ (y= 3) – (z = 0); ↔ z= 0, y= 3, x= i+ y z;

Примерынедопустимыхвыражений:


  • присваивание константе: 2 = x+ y;

  • присваивание функции: getch() = i;

  • присваивание результату операции: (i+ 1) = 2 + y;



    1. Сокращеннаязаписьоперацииприсваивания


В языке Си используются два вида сокращенной записи операции присваивания:

  1. вместо записи: v= v# e;

где # – любая арифметическая операция (операция над битовым представлением операндов), рекомендуется использовать запись v#= e;

Например, i= i+ 2; i+= 2; (знакиоперацийбезпробелов);

  1. вместо записи: x= x# 1;

где # символы, обозначающие операцию инкремента (+1), либо декремента (–1), x– целочисленная переменная (или переменная-указатель), рекомендуется использовать запись:

##x; префиксную, или x##; постфиксную.

Если эти операции используются в чистом виде, то различий между постфиксной и префиксной формами нет. Если же они используются в выражении, то в префиксной форме(##x) сначала значение xизменится на 1, а затем полученный результат будет использован в выражении; в постфиксной форме (x##) – сначала значение переменнойхиспользуется в выражении, а затем изменится на 1. Операции над указателями будут рассмотрены в разд. 9.4.

Пример1: Пример2:


inti, j, k; Смысл записи intn, a, b, c, d; Значения

floatx, y;

...

n= 2; a= b= c= 0;

a= ++n; n=3, a=3

х*= y; x= x*y; a+= 2; a=5

i+= 2; i= i+ 2; b = n++; b=3, n=4

x/= y+15; x= x/(y+ 15); b–= 2;

--k; k = k – 1; c = --n; n=3, c=3 k--; k = k – 1; c *= 2; c=6

j = i++; j = i; i= i+ 1; d= n--; j= ++i; i= i+ 1; j= i; d%= 2;

b=1

d=3, n=2

d=1


    1. Преобразованиетиповоперандоварифметическихопераций


Если операнды арифметических операндов имеют один тип, то и результат операции будет иметь такой же тип.

Но, как правило, в операциях участвуют операнды различных типов. В этом случае они преобразуются к общему типу в порядке увеличения их

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

short, char intunsigned longdouble

float double


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

  • значения типов charи shortвсегда преобразуются в int;

  • если один из операндов имеет тип double, то и другой преобразуется в

double;

  • если один из операндов long, то другой преобразуется в long.

Внимание. Результатом операции 1/3 будет значение 0, чтобы

избежать такого рода ошибок, необходимо явно изменить тип хотя бы одного операнда, т.е. записать, например: 1./3 .

Типы char и int могут свободно смешиваться в арифметических выражениях. Каждая переменная типа charавтоматически преобразуется в

int, что обеспечивает значительную гибкость при проведении преобразований, т.к. над типом intдействия выполняются быстрее, чем над любым другим типом.

При выполнении операции присваивания значение правого операнда преобразуется к типу левого, который и является типом полученного результата. И здесь необходимо быть внимательным, т.к. при некорректном использовании операций присваивания могут возникнуть неконтролируемые ошибки. Так, при преобразовании int в char старший байт просто отбрасывается.

Пусть: float x; int i; тогда и x = i; и i= x; приводят к преобразованиям, причем float преобразуется в int отбрасыванием дробной части.

Тип doubleпреобразуется в floatокруглением.

Длинное целое преобразуется в более короткое целое иchar посредством отбрасывания бит в старших разрядах.

Итак, безопасным преобразованием типов является преобразование в порядке увеличения «размера памяти», обратное преобразование может привести к потере значащих разрядов.

    1. Операцияприведениятипа


В любом выражении преобразование типов может быть осуществлено явно, для этого достаточно перед выражением поставить в круглых скобках атрибут соответствующего типа:

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

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

Операция приведения типа вынуждает компилятор выполнить указанное преобразование, но ответственность за последствия возлагается на программиста. Использовать эту операцию рекомендуется везде, где это необходимо, например:

doublex;

intn= 6, k= 4;

x= (n + k)/3; x= 3, т.к. дробная часть будет отброшена;

x = (double)(n + k)/3; x= 3.333333 использование операции приведения типа позволило избежать округления результата деления целочисленных операндов.

    1. Операциисравнения


В языке Си используются следующие операции сравнения, т.е. отношения между объектами:


==

равно или эквивалентно;

!=

не равно;

<

меньше;

<=

меньше либо равно;

>

больше;

>=

больше либо равно.

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

Общий вид операций отношений:

Операнд_1 ЗнакоперацииОперанд_2


Указанные операции выполняют сравнение значений первого операнда со вторым. Операндами могут быть любые арифметические выражения и указатели.

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

Арифметические операнды преобразуются по правилам, аналогичным для арифметических операций. Операнды-указатели преобразуются в целые числа необходимого типа. Результат сравнения указателей будет корректным в арифметическом смысле лишь для объектов одного массива.

В языке Си нет логического типа данных. Результат операции отношения имеет значение 1, если отношение истинно, или в результате вычислений получено не нулевое значение, воспринимаемое компилятором Си как истина (true), или 0 – в противном случае, т.е. – ложно (false).

Следовательно, операция отношения может использоваться в любых арифметических выражениях.

Операции сравнения на равенство и неравенство имеют меньший приоритет, чем остальные операции отношений.

Примеры использования операций отношений:

y> 0 , x== y, x!= 2 .

Отношения между объектами сложных типов проверяются либо посре- дством последовательного сравнения их элементов (для массивов), либо используя стандартные библиотечные функции, которые будут рассмотрены позже.

    1. Логические операции


Приведем логические операции в порядке убывания относительного приоритета. Их обозначения:

! отрицание (логическое «НЕТ»);

&& конъюнкция (логическое «И»);

|| дизъюнкция (логическое «ИЛИ»).

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

Общий вид операции отрицания

! выражение


Примеры использования операции отрицания:

!0 1

!5 0

x= 10;

! (x> 0) 0

Общий вид операций конъюнкциии дизъюнкции:

Выражение_1 знакоперацииВыражение_2

Особенность операций конъюнкции и дизъюнкции – экономное последовательное вычисление выражений-операндов:

  • если выражение_1 операции «конъюнкция» ложно, то результат операции – ноль и выражение_2 не вычисляется;

  • если выражение_1 операции «дизъюнкция» истинно, то результат операции – единица и выражение_2 не вычисляется.

Например:

y> 0 && x= 7 истина, если оба выражения истинны;

e> 0 || x= 7 истина, если хотя бы одно выражение истинно.

Старшинство операции «И» выше, чем «ИЛИ» и обе они младше операций отношения и равенства.

Относительный приоритет логических операций позволяет пользовать- ся общепринятым математическим стилем записи сложных логических выражений, например:

0 < x< 100 ↔ 0 < x&& x< 100 ;

x> 0,y≤1 x> 0 && y<=1 .

Учет этих свойств очень существенен для написания правильно работающих программ.

    1. Побитовыелогическиеоперации,операциинадбитами


В языке Си предусмотрен набор операций для работы с отдельными битами. Эти операции нельзя применять к переменным вещественного типа.

Обозначения операций над битами:

дополнение (унарная операция); инвертирование (одноместная операция);

& побитовое «И» конъюнкция;

| побитовое включающее «ИЛИ» дизъюнкция;

^ побитовое исключающее «ИЛИ» сложение по модулю 2;

>> сдвиг вправо;

<< сдвиг влево.

Общий вид операции инвертирования (поразрядное отрицание):

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

Остальные операции над битами имеют вид:

Выражение_1 знакоперацииВыражение_2

Операндами операций над битами могут быть только выражения, приводимые к целому типу. Операции(, &, |, ^) выполняются поразрядно над всеми битами операндов (знаковый разряд особо не выделяется):

0xF0 x0F 0xFF & 0x0F x0F

0xF0 | 0x11 xF1

0xF4 ^ 0xF5 x01

Операция & часто используется для маскирования некоторого множества бит. Например, операторw= n& 0177 передает в wсемь младших бит n, полагая остальные равными нулю.

Операции сдвига выполняются также для всех разрядов с потерей выходящих за границы бит.

Операция (|) используется для включения бит w = x | y, устанавливает в единицу те биты в x, которые равны 1 в y.

Необходимо отличать побитовые операции& и| от логических операций && и || , если x = 1, y = 2, то x & y равно нулю, а x&& yравно 1.

0x81 << 1 ↔ 0x02

0x81 >> 1 ↔ 0x40

Если выражение_1 имеет тип unsigned, то при сдвиге вправо освобо- ждающиеся разряды гарантированно заполняются нулями (логический сдвиг). Выражения типа signedмогут, но необязательно, сдвигаться вправо с копированием знакового разряда (арифметический сдвиг). При сдвиге влево освобождающиеся разряды всегда заполняются нулями. Если выражение_2 отрицательно либо больше длины выражения_1 в битах, то результат операции сдвига не определен.

Унарная операция () дает дополнение к целому, т.е. каждый бит со значением 1 получает значение 0 и наоборот.

Операции сдвига << и >> применяются к целочисленным операндам и осуществляют соответственно сдвиг вправо (влево) своего левого операнда на число позиций, задаваемых правым операндом, например, x<< 2 сдвигает x влево на две позиции, заполняя освобождающиеся биты нулями (эквивалентно умножению на 4).

Операции сдвига вправо на kразрядов весьма эффективны для деления, а сдвиг влево – для умножения целых чисел на 2 в степени k:

x<< 1 x*2; x>> 1 x/2 ;

x<< 3 x*8 .

Подобное применение операций сдвига безопасно для беззнаковых и положительных значений выражения_1.

Операции сдвига не учитывают переполнение и потерю значимости.

В математическом смысле операнды логических операций над битами можно рассматривать как отображение некоторых множеств с размерностью не более разрядности операнда на значения {0,1}.

Пусть единица означает обладание элемента множества некоторым свойством, тогда очевидна теоретико-множественная интерпретация рассма- триваемых операций:

– дополнение; | – объединение; & – пересечение. Простейшее применение– проверка нечетности целого числа:

int i;

...

if ( i & 1) printf (" Значениеi четно!");

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

    1. Операция«,»(запятая)


Данная операция используется при организации строго гарантированной последовательности вычисления выражений (обычно используется там, где по синтаксису допустима только одна операция, а необходимо разместить две и более, например, в операторе for). Форма записи:

выражение_1, …, выражение_N;

выражения1, 2,…, Nвычисляются последовательно друг за другом и результатом операции становится значение последнего выражения N, например:

m= ( i= 1, j= i++, k = 6, n= i+ j+ k);

получим последовательность вычислений: i =1, j = i =1, i = 2, k= 6, n= 2+1+6,

и в результате m = n= 9.

В заключение отметим следующую особенность языка Си – любые операции допускаются только со скалярными объектами, причем небольшого размера, порядка размера регистров процессора. Это объясняется ориента- цией языка на задачи системного программирования. Любые действия с составными или сложными объектами – массивами, строками, структурами и т.п. реализуются с помощью стандартных библиотечных функций, работа с которыми будет рассмотрена позже.

1   2   3   4   5   6   7   8   9   ...   67


написать администратору сайта