Основы программирования на языке C

Операции

Разбить на страницы
Показывать лекцию целиком

Основные операции

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

Операция присваивания "="

В языке Си знак равенства не означает "равно". Он означает операцию присваивания некоторого значения. С помощью оператора

year=2004;

переменной c именем year присваивается значение 2004, т.е. элемент слева от знака = - это имя переменной, а элемент справа - ее значение. Мы называем символ = операцией присваивания . В этой операции действие выполняется справа налево.

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

i=i+1;

C математической точки зрения это бессмыслица. Если вы прибавляете единицу к конечному числу, результат не может быть равен исходному числу. Но как оператор присваивания данная строка имеет вполне определенный смысл, который можно выразить, например, такой фразой. Взять значение переменной с именем i, к нему прибавить 1, а затем присвоить новое значение переменной с именем i.

Оператор вида

2004=year;

на языке Си не имеет смысла, поскольку 2004 - число. Мы не можем присвоить константе какое-то значение; ее значением является она сама. Поэтому, помните, что элемент, стоящий слева от знака =, всегда должен быть именем переменной. Операнд - это то, над чем выполняются операции. Например, можно описать процесс "поедания" картошки как применения операции "поедание" к операнду "картошка".

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

/* таблица результатов по шахматам */
 main( )
{
	int l, m, n;
	n=m=l=165;
	printf("l m n\n");
	printf("Счет первой партии %4d %8d %8d\n", l, m, n);
}

Присваивания выполняются справа налево: сначала переменная l получает значение 165, затем переменная m и наконец n. В языке Си имеется несколько других операций присваивания, которые отличаются от описанной операции. Их мы рассмотрим попозже.

Представим еще один пример простой программы:

/* использование операции присваивания */
main( )
{
/* переменные number, ouzo, cost инициализируются конкретными значениями*/
	int number=5;
	float ouzo=13.5;
	int cost=31000;
	printf("number ouzo cost\n");
	printf("number=%d ouzo=%f cost=%d\n",
		number, ouzo, cost);
}

Операция сложения: +

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

printf("%d", 100 + 65);

на печать будет выведено число 165, а не выражение 100+65. Операнды могут быть как переменными, так и константами. Операция + называется "бинарной", или "диадической". Эти названия отражают тот факт, что она имеет дело с двумя операндами.

Пример:

i=j+2;

Переменной i присваивается значение переменной j плюс 2.

Операция вычитания: -

Выполнение операции вычитания приводит к вычитанию числа, расположенного справа от знака -, из числа, стоящего слева от этого знака. Оператор

n = 163.00 - 100.00;

присваивает переменной n значение 63.00.

Операция изменения знака: -

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

teg = -15;
get = -teg;

переменной get будет присвоено значение 15. Когда знак используется подобным образом, данная операция называется "унарной". Такое название указывает на то, что она имеет дело только с одним операндом.

Пример:

x = -x;

Операция изменяет алгебраический знак x.

Операция умножения: *

Операция умножения обозначается знаком *. При выполнении оператора

z = 3 * x

значение переменной x умножается на 3, и результат присваивается переменной z.

Операция деления: /

В языке Си символ / указывает на операцию деления. Величина, стоящая слева от этого знака, делится на величину, расположенную справа от этого знака. Например, в результате выполнения оператора

l = 126.0 / 2.0;

переменной l будет присвоено значение 63.0. Над данными целого типа операция деления производится не так, как над данными с плавающей точкой: в первом случае результат будет целым числом, а во втором - числом с плавающей точкой. В языке Си принято правило, согласно которому дробная часть у результата деления целых чисел отбрасывается. Это действие называется "усечением".

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

main( )
{
	printf("деление целых: 5/4 это %d \n", 5/4);
	printf("деление целых: 6/3 это %d \n", 6/3);
	printf("деление целых: 7/4 это %d \n", 7/4);
	printf("деление чисел с плавающей точкой: 7./4. это %2.2f \n", 7./4.);
	printf("смешанное деление: 7./4 это %2.2f \n", 7./4);
}

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

! Смешения типов следует избегать!

Результат выполнения указанной программы:

деление целых: 5/4 это 1
 деление целых: 6/3 это 2
 деление целых: 7/4 это 1
 деление чисел с плавающей точкой: 7./4. это 1.75
 смешанное деление: 7./4 это 1.75

В результате деления целых чисел происходит отсечение дробной части. Когда мы смешиваем целые числа и числа с плавающей точкой, результат будет таким же, как если бы оба операнда были числами с плавающей точкой. В этом случае перед делением целое преобразуется в число с плавающей точкой. Для того чтобы понять, что происходит в тех случаях, когда в одном операторе используется несколько операций, рассмотрим порядок выполнения операций. Совершенно очевидно, что изменение порядка выполнения действий может приводить к различным результатам. В языке Си каждой операции назначается уровень старшинства. Умножение и деление имеют более высокий уровень, чем сложение и вычитание, поэтому они выполняются первыми. Если же две операции имеют один и тот же уровень старшинства, они выполняются в том порядке, в котором присутствуют в операторе. Для большинства операций обычный порядок - слева направо. Операция = является исключением из этого правила. Многие программисты предпочитают представлять порядок вычислений с помощью дерева выражений. Например, выражение

(a+b)*c

будет выглядеть так:

*
      /   \
     +     c
   a  b

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

Операции в порядке уменьшения уровня старшинства
ОперацииПорядок вычисления
( ) слева направо
- (унарный) слева направо
* / слева направо
+ - (вычитание) слева направо
= справа налево

Дополнительные операции

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

Операция деления по модулю: %

Эта операция используется в целочисленной арифметике. Ее результатом является остаток от деления целого числа, стоящего слева от знака операции, на число, расположенное справа от нее. Например, 63%5, читается как 63 по модулю 5, имеет значение 3, т.к. 63=12*5+3.

В результате выполнения оператора

minutes=time%60;

переменной minutes будет присвоено значение остатка от деления time на 60.

Операция увеличения: ++

Операция увеличения осуществляет следующее простое действие: она увеличивает значение своего операнда на единицу. Существуют две возможности использования данной операции: первая, когда символы ++ находятся слева от переменной ( операнда ), - "префиксная" форма, и вторая, когда символы ++ стоят справа от переменной, - "постфиксная" форма. Эти две формы указанной операции различаются между собой только тем, в какой момент осуществляется увеличение операнда. Префиксная форма изменяет значение операнда перед тем, как операнд используется. Постфиксная форма изменяет значение после того как операнд использовался.

В примере,

j=i++;

переменной j сначала присваивается значение i, затем значение переменной i увеличивается на 1.

Операция уменьшения: --

Каждой операции увеличения соответствует некоторая операция уменьшения, при этом вместо символов ++ мы используем --. Когда символы -- находятся слева от операнда - "префиксная" форма операции уменьшения. Если символы -- стоят справа от операнда - это "постфиксная" форма операции уменьшения.

В соответствии с принятым в языке Си порядком вычислений операции увеличения и уменьшения имеют очень высокий уровень старшинства. Только круглые скобки обладают более высоким приоритетом. Поэтому выражение a/b++ означает (a)/(b++), а не (a/b)++.

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

Перечень операций языка Си

Рассмотрим множество операций языка Си. Описанные операции входят в это множество. Язык Си отличается их большим разнообразием. В этом разделе будет обсуждаться их семантика. Каждая операция характеризуется уровнем приоритета и порядком, в котором эти операции выполняются - слева направо или справа налево. Если все операции выражения имеют один и тот же уровень приоритета, то значение выражения вычисляется слева направо в соответствии с порядком выполнения операций. Все операции с одним и тем же уровнем приоритета имеют один и тот же порядок. Однако, если в выражении имеются операции с различными уровнями приоритета, то сначала выполняются операции с наивысшим уровнем приоритета, затем - следующего за ним приоритета и так далее в порядке убывания приоритета. Операции одного уровня приоритета выполняются в последовательности, указанной их порядком.

Операции, уровень приоритета которых равен 1

Операции вызова функции, индексирования и выбора. В качестве операций языка Си рассматриваются также скобки в вызове функции, квадратные скобки для индексирования массивов, точка и стрелка вправо для выбора компонентов структуры или объединения. Уровень этих операторов равен 1, все операции выполняются слева направо.

Операция вызова функции: ( )

Пример 1:

fe(e1, e2,...,en);

Вызов функции fe с аргументами e1, e2, ..., en. Значением этого выражения является значение, которое возвращает функция.

Пример 2:

x = sqrt (y);

Операция индексирования массива: []

Синтаксис:

array [2]

Значением выражения является третий элемент массива.

Присвоение значения 26 одиннадцатому элементу массива записывается таким образом:

array[10]=26;

Первый элемент массива описывается выражением array[0] (более подробно о массивах описано в лекции 12).

Операция выбора компонентов структуры или объединения: .

Синтаксис:

struct.element

Значением этого выражения является элемент element структуры struct или объединения (см. лекцию 14). Оператор:

struct.element=1963;

присваивает значение 1963 этому элементу.

Операция выбора компонентов структуры с указателем: ->

Синтаксис:

my_birthday->day,

my_birthday - указатель на структуру. Оператор:

my_birthday->day=26;

присваивает значение 26 структурной переменной day, на которую указывает my_birthday.

Операции, уровень приоритета которых равен 2

Унарные операции. Для унарных операций требуется только один операнд ; эти операции либо префиксные, либо постфиксные. Операция sizeof имеет два варианта: префиксная операция и унарная операция.

Операция косвенной ссылки: *

Это указатель на любой тип T, кроме void. Тип результата T.

Использование:

*pe

Значением выражения является переменная, адресуемая указателем pe.

Пример 1:

*ptr=c;

Пример 2:

*fpe;

Значением выражения является функция, адресуемая указателем fpe.

Пример 3:

fpe=*funcname;
(*fpe)(arg1, arg2);

Операция получения адреса:

У этой операции тип операнда есть переменная любого типа, кроме void. Тип результата - указатель на Т.

Использование:

v

Значением выражения является адрес переменной v.

Пример:

myptr=n;

Операция отрицания: -

Тип операнда - арифметический. Тип результата: unsigned, long, double, int.

Операция логического отрицания: !

Тип операнда - арифметический или указатель. Тип результата - int. Если операнд равен 0, то результат равен 1 и наоборот.

Пример:

if(!good) printf("not good");

Операция дополнения до 1: ~

Тип операнда - интегральный. Тип результата: int, long, unsigned.

Пример:

opposite=~mask;

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

Операция увеличения: ++

Тип операнда - арифметический или указатель. Тип результата: int, unsigned, long, double, указатель. Значение операнда увеличивается, и становится новым значением операнда. Значение указателя увеличивается на величину указываемого объекта, значения других операндов увеличиваются на единицу.

Операция увеличения, постфиксная: ++

Тип операнда - арифметический или указатель. Тип результата: int, unsigned, long, double, указатель. Значение операнда увеличивается, но возвращается старое значение операнда. Значение указателя увеличивается на величину указываемого объекта, другие операнды увеличиваются на единицу.

Использование:

iv++

Увеличение iv на 1. Значением этого выражения является значение iv до увеличения.

Пример:

j=i++;

Использование:

pv++;

Увеличение указателя pv на 1, так что он будет указывать на следующий объект того же типа. Значением этого выражения является значение pv до увеличения.

Пример:

*ptr++=0;

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

Операция уменьшения: --

Тип операнда - те же, что и для ++. Тип результата - те же, что и для ++.

Использование:

--iv

Уменьшение iv на 1. Значением этого выражения является значение iv после уменьшения.

Пример:

i=--j;

Операция уменьшения (постфиксная): --

Тип операнда - те же, что и для ++ (постфиксная).

Использование:

iv--

Уменьшение iv на 1. Значением этого выражения является значение iv до уменьшения.

Пример:

j=i--;

Операция определения требуемой памяти в байтах: sizeof

Тип операнда - значение любого типа или имени типа. Тип результата - unsigned. Используется как sizeof (выражение) или sizeof (имя типа).

Пример:

n=sizeof(arname)/sizeof(int);

Число элементов в массиве целых чисел, определяемое как число байт в массиве, поделенное на число байт, занимаемых одним элементом массива.

Операции, уровень приоритета которых равен 3

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

Операция умножения: *

Тип операндов - арифметический. Тип результатов: int, unsigned, long, double.

Использование:

ae1*ae2

Произведение значений ae1*ae2.

Пример:

z=35*5;

Операция деления: /

Тип операндов - арифметический. Тип результата - int, unsigned, long, double.

Использование:

ae1/ae2

Частное от деления ae1 на ae2.

Пример:

i=j/7;

Операция получения остатка: %

Тип операндов - интегральный. Тип результата int, unsigned, long. Знак остатка машинно-зависим.

Использование:

ae1%ae2

Остаток от деления по модулю.

Пример:

j=i%2;

Если i четное число, то j равно нулю.

Операции, уровень приоритета которых равен 4

Уровень приоритета аддитивных операций равен 4. Выполняются эти операции слева направо.

Операция сложения: +

Тип операндов:

  • арифметический;
  • один операнд указатель, другой - интегрального типа; оба операнда не могут быть указателями.
  • Тип результата: int, unsigned, long, double, указатель. Перед сложением значение целого операнда умножается на величину элемента данных, тип которых соответствует типу указателя.

    Использование:

    ae1+ae2

    Сумма значений ae1 и ae2.

    Пример 1:

    i=i+100;

    Первоначальное значение i увеличивает на 100.

    Пример 2:

    last=arname+arsize-1;

    Присваивает переменной last адрес последнего элемента массива arname.

    Операция вычитания: -

    Тип операндов:

  • арифметический;
  • один операнд - указатель, другой - интегрального типа;
  • операнды - указатели одного типа.
  • В первом случае тип результата: int, unsigned, long, double. Во втором случае тип результата - указатель. До вычитания значение целого операнда умножается на величину элемента данных, тип которых соответствует типу указателя. В третьем случае тип результата - int. Результат - число объектов, отделенных двумя указателями.

    Арифметические действия с указателями. Арифметические действия с указателями отличаются от арифметических действий с обычными целыми значениями, и определяются следующим образом. Предположим, что i является целым выражением, а указатели p и q указывают на элементы типа Т. Сложение значения i и p эквивалентно сложению числа ячеек памяти в байтах, занятых i элементами типа Т. Аналогично определяется операция вычитания. Результат вычитания двух указателей типа Т является не разностью значений двух указателей, а числом элементов типа Т, размещенных между ячейками, ссылки на которые обеспечиваются указателями. Никакие другие арифметические действия с указателями не допускаются. Вычитание указателей имеет смысл только для указателей, ссылающихся на элементы одного и того же массива, поскольку только в этом случае разность адресов элементов массива всегда равна произведению целого значения на величину элемента.

    Использование:

    ae1-ae2

    Разность значений ae1 и ae2.

    Пример 1:

    i=j-100;

    Использование:

    pe-ie

    Адрес переменной типа pe, меньше на ie адреса, заданного указателем pe.

    Пример 2:

    first=last-arsize+1;

    Использование:

    pe1-pe2

    Число переменных типа pe в диапазоне от pe2 до pe1.

    Пример 3:

    arsize=last-first;

    Операции, уровень приоритета которых равен 5

    Уровень приоритета операций сдвига равен 5. Порядок выполнения операций - слева направо.

    Операция сдвига влево: <<

    Тип операнда - интегральный. Тип результата - такой же, как у левого операнда. Правый операнд преобразуется к типу int. Левый операнд сдвигается на число разрядов, равное значению правого операнда. Освобождающие разряды заполняются нулями.

    Использование:

    ie1<<ie2

    Двоичное представление ie1 сдвигается влево на ie2 разрядов, освобождающие разряды заполняются нулями.

    Пример:

    four=x<<2;

    Операция сдвига вправо: >>

    Тип операнда - интегральный. Тип результата - такой же, как у левого операнда. Правый операнд преобразуется к типу int. Левый операнд сдвигается на число разрядов, равное значению правого операнда. Сдвиг будет логическим сдвигом, если левый операнд имеет тип unsigned.

    Использование:

    ie1>>ie2

    Двоичное представление ie1 сдвигается вправо на ie2 разрядов. Сдвиг вправо может быть арифметическим (т. е. освобождающиеся слева разряды заполняются значениями знакового разряда) или логическим в зависимости от реализации, однако гарантируется, что сдвиг вправо целых чисел без знака будет логическим и освобождающиеся слева разряды будут заполняться нулями.

    Пример:

    x=x>>3;

    Операции, уровень приоритета которых равен 6

    Уровень приоритета операций отношения равен 6. Выполняются эти операции слева направо.

    Операция меньше: <

    Тип операндов - арифметический или указатель. Тип результата - int.

    Использование:

    ae1<ae2

    Истина, если ae1 меньше, чем ae2.

    Пример:

    if(x<0) printf("negative");

    Операция больше: >

    Тип операндов - арифметический или указатель. Тип результата - int.

    Использование:

    ae1>ae2

    Истина, если ae1 больше, чем ae2.

    Пример:

    if(x>0) printf("positive");

    Операция меньше или равно: <=

    Тип операндов - арифметический или указатель. Тип результата - int.

    Использование:

    ae1<=ae2

    Истина, если ae1 меньше или равно ae2.

    Операция больше или равно: >=

    Тип операндов - арифметический или указатель. Тип результата - int.

    Использование:

    ae1>=ae2

    Истина, если ae1 больше или равно ae2.

    Операции, уровень приоритета которых равен 7

    Уровень приоритетов операций равенства/неравенства равен 7, выполняются они слева направо.

    Операция равенство ==

    Тип операндов - арифметический или указатель. Тип результата - int.

    Использование:

    ie1==ie2

    Истина, если ie1 равно ie2, иначе - ложь.

    Операция неравенство: !=

    Тип операндов - арифметический или указатель. Тип результата - int.

    Единственным целым значением, с которым можно сравнивать указатели, является нулевое значение!

    Использование:

    ie1!=ie2

    Истина, если ie1 не равно ie2.

    Пример:

    while (i!=0) 
    	i=func;

    Операция, уровень приоритета которой равен 8

    Уровень приоритета операции поразрядное И равен 8. Выполняются такие операции слева направо.

    Операция поразрядное И:

    Тип операндов - интегральный. Тип результата: int, long, unsigned.

    Использование:

    ie1  ie2

    Побитовая операция И двоичных представлений ie1 и ie2. Значение выражения содержит 1 во всех разрядах, в которых и ie1 и ie2 содержат 1, и 0 во всех остальных разрядах.

    Пример:

    flag=((xmask)!=0);

    Операция, уровень приоритета которой равен 9

    Уровень приоритета операции поразрядное исключающее ИЛИ равен 9. Порядок выполнения таких операций слева направо.

    Операция поразрядное исключающее или: ^

    Тип операндов - интегральный. Тип результата: int, long, unsigned.

    Использование:

    ie1^ie2

    Побитовая операция исключающее ИЛИ двоичных представлений ie1 и ie2. Значение выражения содержит 1 в тех разрядах, в которых и ie1 и ie2 имеют разные двоичные значения, и 0 во всех остальных разрядах.

    Пример:

    diffbits=x^y;

    Операция, уровень приоритета которой равен 10

    Уровень приоритета операции поразрядное включающее ИЛИ равен 10, порядок выполнения таких операторов - слева направо.

    Операция поразрядное включающее или: |

    Тип операндов - интегральный. Тип результата: int, long, unsigned.

    Использование:

    ie1 | ie2

    Побитовая операция ИЛИ двоичных представлений ie1 и ie2. Значение выражения содержит 1 во всех разрядах, в которых ie1 или ie2 содержат 1, и 0 во всех остальных разрядах.

    Пример:

    attrsum=attr1 | attr2;

    Операция, уровень приоритета которой равен 11

    Уровень приоритета логической (условной) операции и равен 11. Выполняется операция слева направо.

    Операция логическое И:

    Тип операндов - арифметический или указатель. Тип результата - int. Если первый операнд равен 0, то результат равен 0. В противном случае результат будет равен 1, если второй операнд не равен 0, и равен 0, если второй операнд равен 0 (если первый операнд равен 0, то второй операнд не вычисляется).

    Использование:

    e1e2

    Логическая операция И значений e1 и e2. Вначале проверяется значение e1 ; значение e2 проверяется только в том случае, если значение e1 - Истина. Значением выражения является Истина, если значения e1 и e2 - Истина.

    Пример:

    if(p!=NULL*p>7) n++;

    Если p - ненулевой указатель и значение переменной, на которую указывает p, больше, чем 7, то в этом случае n увеличивается на 1. Обратите внимание, что если значение указателя p равно NULL ( 0 ), то выражение *p не имеет смысла.

    Операция, уровень приоритета которой равен 12

    Уровень приоритета операции равен 12, выполняются такие операции слева направо.

    Операция логическое ИЛИ: ||

    Тип операндов - арифметический или указатель. Тип результата int. Если хотя бы один операнд не равен 0, результат равен 1 ; иначе результат будет равен 0.

    Использование:

    e1 || e2

    Логическая операция ИЛИ значений e1 и e2. Вначале проверяется значение e1 ; значение e2 проверяется только в том случае, если значение e1 - ложь. Значением выражения является Истина, если истинно любое значение e1 или e2.

    Пример 1:

    if(x<A || x>B) printf("out of range");

    Операция, уровень приоритета которой равен 13

    Уровень приоритета операции равен 13, выполняются такие операции слева направо.

    Операция условный оператор: ?

    Тип операндов - арифметические; второй и третий операнды могут быть указателями, структурами, объединениями. Тип результата: int, long, unsigned, double, указатель, структура или объединение. Второй и третий операнды преобразуются к одному и тому же типу.

    Условный оператор является единственным оператором, для которого необходимы три операнда ; используется он следующим образом:

    a ? b : c

    где a, b, c - выражения. Если a не равно 0, то результат выражения a ? b : c равен b ; иначе результат равен c. Из двух последних операндов вычисляется только один.

    Использование:

    ae?e1:e2

    или

    pe?e1:e2 (где pe - указатель)

    Если истинно ae или pe, то выполняется e1 ; иначе выполняется e2. Значением этого выражения является значение выражения e1 или e2.

    Пример:

    abs=(i<=0)?-i:i;

    Операция, уровень приоритета которой равен 14

    Уровень приоритета операции равен 14, выполняются такие операции справа налево.

    Операция простое присваивание "="

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

    Использование:

    v=e

    Присваивание значения e переменной v.

    Пример:

    x=y;

    Операция сложное присваивание "="

    Обозначим <знак> один из знаков : +, -, *, /, %, >>, <<, , ^, |.

    В результате выполнения операции присваивания

    v=e

    где v - переменная, а e - выражение, значение выражения становится новым значением переменной v.

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

    v <знак>= e

    приблизительно эквивалентна оператору присваивания

    v = v<знак> e

    Пример 1:

    y+=2; /* Увеличение переменной y на 2 */
    p+=n;
    x-=3;
    ptr-=2;
    timesx*=x;
    x/=2;
    x%=10;
    x>>=4;
    x<<=1;
    remitems=mask;
    control^=seton;
    additems |=mask;

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

    v <знак>= e

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

    v = v <знак> e

    этот операнд вычисляется дважды. Это различие проявляется в побочных эффектах, связанных с вычислением операнда v, например, при изменении значения какой-либо переменной. Рассмотрим это на примерах:

    a[i++]* = n;

    При выполнении вычисление левого операнда дает побочный эффект - увеличение значения переменной i. Следовательно, это присваивание не эквивалентно присваиванию

    a[i++] = a[i++]*n;.

    Эквивалентом первой операции присваивания может служить последовательность операций

    a[i]=a[i]*n;
    i=i+1;

    а эквивалентом второй - последовательность операций

    a[i]=a[i+1]*n;
    i=i+2;

    или последовательность операций

    a[i+1]=a[i]*n;
    i=i+2;

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

    Операция, уровень приоритета которой равен 15

    Уровень приоритета операции равен 15, выполняются такие операции слева направо.

    Операция запятая: ,

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

    Использование:

    e1,e2

    Сначала выполняется выражение e1, потом выражение е2. Значением всего выражения является значение выражения е2.

    Пример:

    for(i=A,j=B;i<j;i++,j--) 
    	/* организация циклического повторения. 
    		 Оператор со счетчиком */
    p[i]=p[j];

    Примеры простых задач

    /* Задача № 1 (пример на использование операции *) 
    Определить площадь боковой поверхности конуса радиуса 
    r и имеющего длину образующей l.*/
    #include <stdio.h>
    #include <math.h>
    /* подключение библиотеки математических функций */
    const float pi=3.14159;
    float r=10; float l=50; float s;
    main()
    {
    	s=pi*r*l;
    	printf("\n Площадь боковой поверхности s=%f",s);
    }
    
    /* Задача № 2 (пример на использование операций +,
     * и /. Тело движется прямолинейно с ускорением. 
     Даны а(м/сек2) - ускорение, V(M/C) - начальная 
     скорость. Требуется определить, какой путь пройдет 
     тело за t секунд.*/
    #include <stdio.h>
    float a, v, t, s ;
    main()
    {
    	a=20.2;
    	v=50.3;
    	t=65;
    	s=(v*t)+(a*t*t/2);
    	printf("\n Путь s=%f M",s);
    }
    /* Задача № 3 (пример на использование операций =, 
    / и вычисления степени). Вычислите среднее арифметическое 
    и среднее геометрическое трех чисел а,b,с.*/ 
    #include <stdio.h> 
    #include <math.h> 
    float a=b=c=2005.1; float x,y;
    main ()
    {
    	x=(a+b+c)/3;
    	y=pow( (a*b*c),(1/3)); 
    	/*функция pow берется из библиотеки math.h*/
    	printf("\n среднее арифметическое x=%f",x);
    	printf("\n среднее геометрическое y=%f",y);
    }
    /* Задача № 4 (пример на использование операций 
    =,*, / и функции hypot. Даны катеты прямоугольного 
    треугольника. Найти его гипотенузу и площадь.*/ 
    #include <stdio.h>
    #include <math.h> 
    float x=y=50.7; float z,s; 
    main() 
    {
    	z=hypot(x, y) ;/* вычисление гипотенузы*/ 
    	s=x*y/2;
    	printf("\n гипотенуза=%f см",z); 
    	printf("\n Плoщaдь=%f кв см",s);
    }
    Страницы:

    Основные операции

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

    Операция присваивания "="

    В языке Си знак равенства не означает "равно". Он означает операцию присваивания некоторого значения. С помощью оператора

    year=2004;

    переменной c именем year присваивается значение 2004, т.е. элемент слева от знака = - это имя переменной, а элемент справа - ее значение. Мы называем символ = операцией присваивания . В этой операции действие выполняется справа налево.

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

    i=i+1;

    C математической точки зрения это бессмыслица. Если вы прибавляете единицу к конечному числу, результат не может быть равен исходному числу. Но как оператор присваивания данная строка имеет вполне определенный смысл, который можно выразить, например, такой фразой. Взять значение переменной с именем i, к нему прибавить 1, а затем присвоить новое значение переменной с именем i.

    Оператор вида

    2004=year;

    на языке Си не имеет смысла, поскольку 2004 - число. Мы не можем присвоить константе какое-то значение; ее значением является она сама. Поэтому, помните, что элемент, стоящий слева от знака =, всегда должен быть именем переменной. Операнд - это то, над чем выполняются операции. Например, можно описать процесс "поедания" картошки как применения операции "поедание" к операнду "картошка".

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

    /* таблица результатов по шахматам */
     main( )
    {
    	int l, m, n;
    	n=m=l=165;
    	printf("l m n\n");
    	printf("Счет первой партии %4d %8d %8d\n", l, m, n);
    }

    Присваивания выполняются справа налево: сначала переменная l получает значение 165, затем переменная m и наконец n. В языке Си имеется несколько других операций присваивания, которые отличаются от описанной операции. Их мы рассмотрим попозже.

    Представим еще один пример простой программы:

    /* использование операции присваивания */
    main( )
    {
    /* переменные number, ouzo, cost инициализируются конкретными значениями*/
    	int number=5;
    	float ouzo=13.5;
    	int cost=31000;
    	printf("number ouzo cost\n");
    	printf("number=%d ouzo=%f cost=%d\n",
    		number, ouzo, cost);
    }

    Операция сложения: +

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

    printf("%d", 100 + 65);

    на печать будет выведено число 165, а не выражение 100+65. Операнды могут быть как переменными, так и константами. Операция + называется "бинарной", или "диадической". Эти названия отражают тот факт, что она имеет дело с двумя операндами.

    Пример:

    i=j+2;

    Переменной i присваивается значение переменной j плюс 2.

    Операция вычитания: -

    Выполнение операции вычитания приводит к вычитанию числа, расположенного справа от знака -, из числа, стоящего слева от этого знака. Оператор

    n = 163.00 - 100.00;

    присваивает переменной n значение 63.00.

    Операция изменения знака: -

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

    teg = -15;
    get = -teg;

    переменной get будет присвоено значение 15. Когда знак используется подобным образом, данная операция называется "унарной". Такое название указывает на то, что она имеет дело только с одним операндом.

    Пример:

    x = -x;

    Операция изменяет алгебраический знак x.

    Операция умножения: *

    Операция умножения обозначается знаком *. При выполнении оператора

    z = 3 * x

    значение переменной x умножается на 3, и результат присваивается переменной z.

    Операция деления: /

    В языке Си символ / указывает на операцию деления. Величина, стоящая слева от этого знака, делится на величину, расположенную справа от этого знака. Например, в результате выполнения оператора

    l = 126.0 / 2.0;

    переменной l будет присвоено значение 63.0. Над данными целого типа операция деления производится не так, как над данными с плавающей точкой: в первом случае результат будет целым числом, а во втором - числом с плавающей точкой. В языке Си принято правило, согласно которому дробная часть у результата деления целых чисел отбрасывается. Это действие называется "усечением".

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

    main( )
    {
    	printf("деление целых: 5/4 это %d \n", 5/4);
    	printf("деление целых: 6/3 это %d \n", 6/3);
    	printf("деление целых: 7/4 это %d \n", 7/4);
    	printf("деление чисел с плавающей точкой: 7./4. это %2.2f \n", 7./4.);
    	printf("смешанное деление: 7./4 это %2.2f \n", 7./4);
    }

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

    ! Смешения типов следует избегать!

    Результат выполнения указанной программы:

    деление целых: 5/4 это 1
     деление целых: 6/3 это 2
     деление целых: 7/4 это 1
     деление чисел с плавающей точкой: 7./4. это 1.75
     смешанное деление: 7./4 это 1.75

    В результате деления целых чисел происходит отсечение дробной части. Когда мы смешиваем целые числа и числа с плавающей точкой, результат будет таким же, как если бы оба операнда были числами с плавающей точкой. В этом случае перед делением целое преобразуется в число с плавающей точкой. Для того чтобы понять, что происходит в тех случаях, когда в одном операторе используется несколько операций, рассмотрим порядок выполнения операций. Совершенно очевидно, что изменение порядка выполнения действий может приводить к различным результатам. В языке Си каждой операции назначается уровень старшинства. Умножение и деление имеют более высокий уровень, чем сложение и вычитание, поэтому они выполняются первыми. Если же две операции имеют один и тот же уровень старшинства, они выполняются в том порядке, в котором присутствуют в операторе. Для большинства операций обычный порядок - слева направо. Операция = является исключением из этого правила. Многие программисты предпочитают представлять порядок вычислений с помощью дерева выражений. Например, выражение

    (a+b)*c

    будет выглядеть так:

    *
          /   \
         +     c
       a  b

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

    Операции в порядке уменьшения уровня старшинства
    ОперацииПорядок вычисления
    ( ) слева направо
    - (унарный) слева направо
    * / слева направо
    + - (вычитание) слева направо
    = справа налево

    Дополнительные операции

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

    Операция деления по модулю: %

    Эта операция используется в целочисленной арифметике. Ее результатом является остаток от деления целого числа, стоящего слева от знака операции, на число, расположенное справа от нее. Например, 63%5, читается как 63 по модулю 5, имеет значение 3, т.к. 63=12*5+3.

    В результате выполнения оператора

    minutes=time%60;

    переменной minutes будет присвоено значение остатка от деления time на 60.

    Операция увеличения: ++

    Операция увеличения осуществляет следующее простое действие: она увеличивает значение своего операнда на единицу. Существуют две возможности использования данной операции: первая, когда символы ++ находятся слева от переменной ( операнда ), - "префиксная" форма, и вторая, когда символы ++ стоят справа от переменной, - "постфиксная" форма. Эти две формы указанной операции различаются между собой только тем, в какой момент осуществляется увеличение операнда. Префиксная форма изменяет значение операнда перед тем, как операнд используется. Постфиксная форма изменяет значение после того как операнд использовался.

    В примере,

    j=i++;

    переменной j сначала присваивается значение i, затем значение переменной i увеличивается на 1.

    Операция уменьшения: --

    Каждой операции увеличения соответствует некоторая операция уменьшения, при этом вместо символов ++ мы используем --. Когда символы -- находятся слева от операнда - "префиксная" форма операции уменьшения. Если символы -- стоят справа от операнда - это "постфиксная" форма операции уменьшения.

    В соответствии с принятым в языке Си порядком вычислений операции увеличения и уменьшения имеют очень высокий уровень старшинства. Только круглые скобки обладают более высоким приоритетом. Поэтому выражение a/b++ означает (a)/(b++), а не (a/b)++.

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

    Перечень операций языка Си

    Рассмотрим множество операций языка Си. Описанные операции входят в это множество. Язык Си отличается их большим разнообразием. В этом разделе будет обсуждаться их семантика. Каждая операция характеризуется уровнем приоритета и порядком, в котором эти операции выполняются - слева направо или справа налево. Если все операции выражения имеют один и тот же уровень приоритета, то значение выражения вычисляется слева направо в соответствии с порядком выполнения операций. Все операции с одним и тем же уровнем приоритета имеют один и тот же порядок. Однако, если в выражении имеются операции с различными уровнями приоритета, то сначала выполняются операции с наивысшим уровнем приоритета, затем - следующего за ним приоритета и так далее в порядке убывания приоритета. Операции одного уровня приоритета выполняются в последовательности, указанной их порядком.

    Операции, уровень приоритета которых равен 1

    Операции вызова функции, индексирования и выбора. В качестве операций языка Си рассматриваются также скобки в вызове функции, квадратные скобки для индексирования массивов, точка и стрелка вправо для выбора компонентов структуры или объединения. Уровень этих операторов равен 1, все операции выполняются слева направо.

    Операция вызова функции: ( )

    Пример 1:

    fe(e1, e2,...,en);

    Вызов функции fe с аргументами e1, e2, ..., en. Значением этого выражения является значение, которое возвращает функция.

    Пример 2:

    x = sqrt (y);

    Операция индексирования массива: []

    Синтаксис:

    array [2]

    Значением выражения является третий элемент массива.

    Присвоение значения 26 одиннадцатому элементу массива записывается таким образом:

    array[10]=26;

    Первый элемент массива описывается выражением array[0] (более подробно о массивах описано в лекции 12).

    Операция выбора компонентов структуры или объединения: .

    Синтаксис:

    struct.element

    Значением этого выражения является элемент element структуры struct или объединения (см. лекцию 14). Оператор:

    struct.element=1963;

    присваивает значение 1963 этому элементу.

    Операция выбора компонентов структуры с указателем: ->

    Синтаксис:

    my_birthday->day,

    my_birthday - указатель на структуру. Оператор:

    my_birthday->day=26;

    присваивает значение 26 структурной переменной day, на которую указывает my_birthday.

    Операции, уровень приоритета которых равен 2

    Унарные операции. Для унарных операций требуется только один операнд ; эти операции либо префиксные, либо постфиксные. Операция sizeof имеет два варианта: префиксная операция и унарная операция.

    Операция косвенной ссылки: *

    Это указатель на любой тип T, кроме void. Тип результата T.

    Использование:

    *pe

    Значением выражения является переменная, адресуемая указателем pe.

    Пример 1:

    *ptr=c;

    Пример 2:

    *fpe;

    Значением выражения является функция, адресуемая указателем fpe.

    Пример 3:

    fpe=*funcname;
    (*fpe)(arg1, arg2);

    Операция получения адреса:

    У этой операции тип операнда есть переменная любого типа, кроме void. Тип результата - указатель на Т.

    Использование:

    v

    Значением выражения является адрес переменной v.

    Пример:

    myptr=n;

    Операция отрицания: -

    Тип операнда - арифметический. Тип результата: unsigned, long, double, int.

    Операция логического отрицания: !

    Тип операнда - арифметический или указатель. Тип результата - int. Если операнд равен 0, то результат равен 1 и наоборот.

    Пример:

    if(!good) printf("not good");

    Операция дополнения до 1: ~

    Тип операнда - интегральный. Тип результата: int, long, unsigned.

    Пример:

    opposite=~mask;

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

    Операция увеличения: ++

    Тип операнда - арифметический или указатель. Тип результата: int, unsigned, long, double, указатель. Значение операнда увеличивается, и становится новым значением операнда. Значение указателя увеличивается на величину указываемого объекта, значения других операндов увеличиваются на единицу.

    Операция увеличения, постфиксная: ++

    Тип операнда - арифметический или указатель. Тип результата: int, unsigned, long, double, указатель. Значение операнда увеличивается, но возвращается старое значение операнда. Значение указателя увеличивается на величину указываемого объекта, другие операнды увеличиваются на единицу.

    Использование:

    iv++

    Увеличение iv на 1. Значением этого выражения является значение iv до увеличения.

    Пример:

    j=i++;

    Использование:

    pv++;

    Увеличение указателя pv на 1, так что он будет указывать на следующий объект того же типа. Значением этого выражения является значение pv до увеличения.

    Пример:

    *ptr++=0;

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

    Операция уменьшения: --

    Тип операнда - те же, что и для ++. Тип результата - те же, что и для ++.

    Использование:

    --iv

    Уменьшение iv на 1. Значением этого выражения является значение iv после уменьшения.

    Пример:

    i=--j;

    Операция уменьшения (постфиксная): --

    Тип операнда - те же, что и для ++ (постфиксная).

    Использование:

    iv--

    Уменьшение iv на 1. Значением этого выражения является значение iv до уменьшения.

    Пример:

    j=i--;

    Операция определения требуемой памяти в байтах: sizeof

    Тип операнда - значение любого типа или имени типа. Тип результата - unsigned. Используется как sizeof (выражение) или sizeof (имя типа).

    Пример:

    n=sizeof(arname)/sizeof(int);

    Число элементов в массиве целых чисел, определяемое как число байт в массиве, поделенное на число байт, занимаемых одним элементом массива.

    Операции, уровень приоритета которых равен 3

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

    Операция умножения: *

    Тип операндов - арифметический. Тип результатов: int, unsigned, long, double.

    Использование:

    ae1*ae2

    Произведение значений ae1*ae2.

    Пример:

    z=35*5;

    Операция деления: /

    Тип операндов - арифметический. Тип результата - int, unsigned, long, double.

    Использование:

    ae1/ae2

    Частное от деления ae1 на ae2.

    Пример:

    i=j/7;

    Операция получения остатка: %

    Тип операндов - интегральный. Тип результата int, unsigned, long. Знак остатка машинно-зависим.

    Использование:

    ae1%ae2

    Остаток от деления по модулю.

    Пример:

    j=i%2;

    Если i четное число, то j равно нулю.

    Операции, уровень приоритета которых равен 4

    Уровень приоритета аддитивных операций равен 4. Выполняются эти операции слева направо.

    Операция сложения: +

    Тип операндов:

  • арифметический;
  • один операнд указатель, другой - интегрального типа; оба операнда не могут быть указателями.
  • Тип результата: int, unsigned, long, double, указатель. Перед сложением значение целого операнда умножается на величину элемента данных, тип которых соответствует типу указателя.

    Использование:

    ae1+ae2

    Сумма значений ae1 и ae2.

    Пример 1:

    i=i+100;

    Первоначальное значение i увеличивает на 100.

    Пример 2:

    last=arname+arsize-1;

    Присваивает переменной last адрес последнего элемента массива arname.

    Операция вычитания: -

    Тип операндов:

  • арифметический;
  • один операнд - указатель, другой - интегрального типа;
  • операнды - указатели одного типа.
  • В первом случае тип результата: int, unsigned, long, double. Во втором случае тип результата - указатель. До вычитания значение целого операнда умножается на величину элемента данных, тип которых соответствует типу указателя. В третьем случае тип результата - int. Результат - число объектов, отделенных двумя указателями.

    Арифметические действия с указателями. Арифметические действия с указателями отличаются от арифметических действий с обычными целыми значениями, и определяются следующим образом. Предположим, что i является целым выражением, а указатели p и q указывают на элементы типа Т. Сложение значения i и p эквивалентно сложению числа ячеек памяти в байтах, занятых i элементами типа Т. Аналогично определяется операция вычитания. Результат вычитания двух указателей типа Т является не разностью значений двух указателей, а числом элементов типа Т, размещенных между ячейками, ссылки на которые обеспечиваются указателями. Никакие другие арифметические действия с указателями не допускаются. Вычитание указателей имеет смысл только для указателей, ссылающихся на элементы одного и того же массива, поскольку только в этом случае разность адресов элементов массива всегда равна произведению целого значения на величину элемента.

    Использование:

    ae1-ae2

    Разность значений ae1 и ae2.

    Пример 1:

    i=j-100;

    Использование:

    pe-ie

    Адрес переменной типа pe, меньше на ie адреса, заданного указателем pe.

    Пример 2:

    first=last-arsize+1;

    Использование:

    pe1-pe2

    Число переменных типа pe в диапазоне от pe2 до pe1.

    Пример 3:

    arsize=last-first;

    Операции, уровень приоритета которых равен 5

    Уровень приоритета операций сдвига равен 5. Порядок выполнения операций - слева направо.

    Операция сдвига влево: <<

    Тип операнда - интегральный. Тип результата - такой же, как у левого операнда. Правый операнд преобразуется к типу int. Левый операнд сдвигается на число разрядов, равное значению правого операнда. Освобождающие разряды заполняются нулями.

    Использование:

    ie1<<ie2

    Двоичное представление ie1 сдвигается влево на ie2 разрядов, освобождающие разряды заполняются нулями.

    Пример:

    four=x<<2;

    Операция сдвига вправо: >>

    Тип операнда - интегральный. Тип результата - такой же, как у левого операнда. Правый операнд преобразуется к типу int. Левый операнд сдвигается на число разрядов, равное значению правого операнда. Сдвиг будет логическим сдвигом, если левый операнд имеет тип unsigned.

    Использование:

    ie1>>ie2

    Двоичное представление ie1 сдвигается вправо на ie2 разрядов. Сдвиг вправо может быть арифметическим (т. е. освобождающиеся слева разряды заполняются значениями знакового разряда) или логическим в зависимости от реализации, однако гарантируется, что сдвиг вправо целых чисел без знака будет логическим и освобождающиеся слева разряды будут заполняться нулями.

    Пример:

    x=x>>3;

    Операции, уровень приоритета которых равен 6

    Уровень приоритета операций отношения равен 6. Выполняются эти операции слева направо.

    Операция меньше: <

    Тип операндов - арифметический или указатель. Тип результата - int.

    Использование:

    ae1<ae2

    Истина, если ae1 меньше, чем ae2.

    Пример:

    if(x<0) printf("negative");

    Операция больше: >

    Тип операндов - арифметический или указатель. Тип результата - int.

    Использование:

    ae1>ae2

    Истина, если ae1 больше, чем ae2.

    Пример:

    if(x>0) printf("positive");

    Операция меньше или равно: <=

    Тип операндов - арифметический или указатель. Тип результата - int.

    Использование:

    ae1<=ae2

    Истина, если ae1 меньше или равно ae2.

    Операция больше или равно: >=

    Тип операндов - арифметический или указатель. Тип результата - int.

    Использование:

    ae1>=ae2

    Истина, если ae1 больше или равно ae2.

    Операции, уровень приоритета которых равен 7

    Уровень приоритетов операций равенства/неравенства равен 7, выполняются они слева направо.

    Операция равенство ==

    Тип операндов - арифметический или указатель. Тип результата - int.

    Использование:

    ie1==ie2

    Истина, если ie1 равно ie2, иначе - ложь.

    Операция неравенство: !=

    Тип операндов - арифметический или указатель. Тип результата - int.

    Единственным целым значением, с которым можно сравнивать указатели, является нулевое значение!

    Использование:

    ie1!=ie2

    Истина, если ie1 не равно ie2.

    Пример:

    while (i!=0) 
    	i=func;

    Операция, уровень приоритета которой равен 8

    Уровень приоритета операции поразрядное И равен 8. Выполняются такие операции слева направо.

    Операция поразрядное И:

    Тип операндов - интегральный. Тип результата: int, long, unsigned.

    Использование:

    ie1  ie2

    Побитовая операция И двоичных представлений ie1 и ie2. Значение выражения содержит 1 во всех разрядах, в которых и ie1 и ie2 содержат 1, и 0 во всех остальных разрядах.

    Пример:

    flag=((xmask)!=0);

    Операция, уровень приоритета которой равен 9

    Уровень приоритета операции поразрядное исключающее ИЛИ равен 9. Порядок выполнения таких операций слева направо.

    Операция поразрядное исключающее или: ^

    Тип операндов - интегральный. Тип результата: int, long, unsigned.

    Использование:

    ie1^ie2

    Побитовая операция исключающее ИЛИ двоичных представлений ie1 и ie2. Значение выражения содержит 1 в тех разрядах, в которых и ie1 и ie2 имеют разные двоичные значения, и 0 во всех остальных разрядах.

    Пример:

    diffbits=x^y;

    Операция, уровень приоритета которой равен 10

    Уровень приоритета операции поразрядное включающее ИЛИ равен 10, порядок выполнения таких операторов - слева направо.

    Операция поразрядное включающее или: |

    Тип операндов - интегральный. Тип результата: int, long, unsigned.

    Использование:

    ie1 | ie2

    Побитовая операция ИЛИ двоичных представлений ie1 и ie2. Значение выражения содержит 1 во всех разрядах, в которых ie1 или ie2 содержат 1, и 0 во всех остальных разрядах.

    Пример:

    attrsum=attr1 | attr2;

    Операция, уровень приоритета которой равен 11

    Уровень приоритета логической (условной) операции и равен 11. Выполняется операция слева направо.

    Операция логическое И:

    Тип операндов - арифметический или указатель. Тип результата - int. Если первый операнд равен 0, то результат равен 0. В противном случае результат будет равен 1, если второй операнд не равен 0, и равен 0, если второй операнд равен 0 (если первый операнд равен 0, то второй операнд не вычисляется).

    Использование:

    e1e2

    Логическая операция И значений e1 и e2. Вначале проверяется значение e1 ; значение e2 проверяется только в том случае, если значение e1 - Истина. Значением выражения является Истина, если значения e1 и e2 - Истина.

    Пример:

    if(p!=NULL*p>7) n++;

    Если p - ненулевой указатель и значение переменной, на которую указывает p, больше, чем 7, то в этом случае n увеличивается на 1. Обратите внимание, что если значение указателя p равно NULL ( 0 ), то выражение *p не имеет смысла.

    Операция, уровень приоритета которой равен 12

    Уровень приоритета операции равен 12, выполняются такие операции слева направо.

    Операция логическое ИЛИ: ||

    Тип операндов - арифметический или указатель. Тип результата int. Если хотя бы один операнд не равен 0, результат равен 1 ; иначе результат будет равен 0.

    Использование:

    e1 || e2

    Логическая операция ИЛИ значений e1 и e2. Вначале проверяется значение e1 ; значение e2 проверяется только в том случае, если значение e1 - ложь. Значением выражения является Истина, если истинно любое значение e1 или e2.

    Пример 1:

    if(x<A || x>B) printf("out of range");

    Операция, уровень приоритета которой равен 13

    Уровень приоритета операции равен 13, выполняются такие операции слева направо.

    Операция условный оператор: ?

    Тип операндов - арифметические; второй и третий операнды могут быть указателями, структурами, объединениями. Тип результата: int, long, unsigned, double, указатель, структура или объединение. Второй и третий операнды преобразуются к одному и тому же типу.

    Условный оператор является единственным оператором, для которого необходимы три операнда ; используется он следующим образом:

    a ? b : c

    где a, b, c - выражения. Если a не равно 0, то результат выражения a ? b : c равен b ; иначе результат равен c. Из двух последних операндов вычисляется только один.

    Использование:

    ae?e1:e2

    или

    pe?e1:e2 (где pe - указатель)

    Если истинно ae или pe, то выполняется e1 ; иначе выполняется e2. Значением этого выражения является значение выражения e1 или e2.

    Пример:

    abs=(i<=0)?-i:i;

    Операция, уровень приоритета которой равен 14

    Уровень приоритета операции равен 14, выполняются такие операции справа налево.

    Операция простое присваивание "="

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

    Использование:

    v=e

    Присваивание значения e переменной v.

    Пример:

    x=y;

    Операция сложное присваивание "="

    Обозначим <знак> один из знаков : +, -, *, /, %, >>, <<, , ^, |.

    В результате выполнения операции присваивания

    v=e

    где v - переменная, а e - выражение, значение выражения становится новым значением переменной v.

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

    v <знак>= e

    приблизительно эквивалентна оператору присваивания

    v = v<знак> e

    Пример 1:

    y+=2; /* Увеличение переменной y на 2 */
    p+=n;
    x-=3;
    ptr-=2;
    timesx*=x;
    x/=2;
    x%=10;
    x>>=4;
    x<<=1;
    remitems=mask;
    control^=seton;
    additems |=mask;

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

    v <знак>= e

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

    v = v <знак> e

    этот операнд вычисляется дважды. Это различие проявляется в побочных эффектах, связанных с вычислением операнда v, например, при изменении значения какой-либо переменной. Рассмотрим это на примерах:

    a[i++]* = n;

    При выполнении вычисление левого операнда дает побочный эффект - увеличение значения переменной i. Следовательно, это присваивание не эквивалентно присваиванию

    a[i++] = a[i++]*n;.

    Эквивалентом первой операции присваивания может служить последовательность операций

    a[i]=a[i]*n;
    i=i+1;

    а эквивалентом второй - последовательность операций

    a[i]=a[i+1]*n;
    i=i+2;

    или последовательность операций

    a[i+1]=a[i]*n;
    i=i+2;

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

    Операция, уровень приоритета которой равен 15

    Уровень приоритета операции равен 15, выполняются такие операции слева направо.

    Операция запятая: ,

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

    Использование:

    e1,e2

    Сначала выполняется выражение e1, потом выражение е2. Значением всего выражения является значение выражения е2.

    Пример:

    for(i=A,j=B;i<j;i++,j--) 
    	/* организация циклического повторения. 
    		 Оператор со счетчиком */
    p[i]=p[j];

    Примеры простых задач

    /* Задача № 1 (пример на использование операции *) 
    Определить площадь боковой поверхности конуса радиуса 
    r и имеющего длину образующей l.*/
    #include <stdio.h>
    #include <math.h>
    /* подключение библиотеки математических функций */
    const float pi=3.14159;
    float r=10; float l=50; float s;
    main()
    {
    	s=pi*r*l;
    	printf("\n Площадь боковой поверхности s=%f",s);
    }
    
    /* Задача № 2 (пример на использование операций +,
     * и /. Тело движется прямолинейно с ускорением. 
     Даны а(м/сек2) - ускорение, V(M/C) - начальная 
     скорость. Требуется определить, какой путь пройдет 
     тело за t секунд.*/
    #include <stdio.h>
    float a, v, t, s ;
    main()
    {
    	a=20.2;
    	v=50.3;
    	t=65;
    	s=(v*t)+(a*t*t/2);
    	printf("\n Путь s=%f M",s);
    }
    /* Задача № 3 (пример на использование операций =, 
    / и вычисления степени). Вычислите среднее арифметическое 
    и среднее геометрическое трех чисел а,b,с.*/ 
    #include <stdio.h> 
    #include <math.h> 
    float a=b=c=2005.1; float x,y;
    main ()
    {
    	x=(a+b+c)/3;
    	y=pow( (a*b*c),(1/3)); 
    	/*функция pow берется из библиотеки math.h*/
    	printf("\n среднее арифметическое x=%f",x);
    	printf("\n среднее геометрическое y=%f",y);
    }
    /* Задача № 4 (пример на использование операций 
    =,*, / и функции hypot. Даны катеты прямоугольного 
    треугольника. Найти его гипотенузу и площадь.*/ 
    #include <stdio.h>
    #include <math.h> 
    float x=y=50.7; float z,s; 
    main() 
    {
    	z=hypot(x, y) ;/* вычисление гипотенузы*/ 
    	s=x*y/2;
    	printf("\n гипотенуза=%f см",z); 
    	printf("\n Плoщaдь=%f кв см",s);
    }
    Вернуться к учебному плану