
лекции_1 / Операции
.pdf
07.06.13 |
Операции |
Национальный Открытый Университет "ИНТУИТ": www.intuit.ru Нина Калинина, Нина Костюкова Лекция 3. Операции
Основные операции
Рассмотрим способы обработки данных - для этого язык Си имеет широкий набор возможностей. Основные арифметические операции: сложения, вычитания, умножения, деления. Операции в языке Си применяются для представления арифметических действий. Например, выполнение операции + приводит к сложению двух величин, стоящих слева и справа от этого знака. Рассмотрим операции =, +, -, *, /. В языке Си нет операции возведения в степень.
Операция присваивания "="
В языке Си знак равенства не означает "равно". Он означает операцию присваивания некоторого значения. С помощью оператора
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. В языке Си имеется несколько других операций присваивания, которые отличаются от описанной операции. Их мы рассмотрим попозже.
Представим еще один пример простой программы:
www.intuit.ru/studies/professional_skill_improvements/1747/courses/43/print_lecture/655 |
1/16 |
07.06.13 |
Операции |
/* использование операции присваивания */ 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.
www.intuit.ru/studies/professional_skill_improvements/1747/courses/43/print_lecture/655 |
2/16 |
07.06.13 |
Операции |
Операция деления: /
В языке Си символ / указывает на операцию деления. Величина, стоящая слева от этого знака, делится на величину, расположенную справа от этого знака. Например, в результате выполнения оператора
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
www.intuit.ru/studies/professional_skill_improvements/1747/courses/43/print_lecture/655 |
3/16 |
07.06.13 |
Операции |
Мы можем составить таблицу правил описанных нами операций. В дальнейшем мы приведем таблицу, где содержатся правила, относящиеся ко всем операциям языка Си.
Таблица 1.1. Операции в порядке уменьшения уровня старшинства
Операции Порядок вычисления
( ) |
слева направо |
- (унарный) |
слева направо |
* / |
слева направо |
+ - (вычитание) слева направо
=справа налево
Дополнительные операции
В языке Си имеется около сорока операций. Те операции, которые мы рассмотрели, являются наиболее общеупотребительными. Рассмотрим еще три операции, наиболее используемые программистами.
Операция деления по модулю: %
Эта операция используется в целочисленной арифметике. Ее результатом является остаток от деления целого числа, стоящего слева от знака операции, на число, расположенное справа от нее. Например, 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)++.
!Не применяйте операции увеличения или уменьшения к переменной, присутствующей в более чем одном аргументе функции. Не применяйте операции увеличения или уменьшения к переменной, которая входит в выражение более одного раза.
www.intuit.ru/studies/professional_skill_improvements/1747/courses/43/print_lecture/655 |
4/16 |
07.06.13 |
Операции |
Перечень операций языка Си
Рассмотрим множество операций языка Си. Описанные операции входят в это множество. Язык Си отличается их большим разнообразием. В этом разделе будет обсуждаться их семантика. Каждая операция характеризуется уровнем приоритета и порядком, в котором эти операции выполняются - слева направо или справа налево. Если все операции выражения имеют один и тот же уровень приоритета, то значение выражения вычисляется слева направо в соответствии с порядком выполнения операций. Все операции с одним и тем же уровнем приоритета имеют один и тот же порядок. Однако, если в выражении имеются операции с различными уровнями приоритета, то сначала выполняются операции с наивысшим уровнем приоритета, затем - следующего за ним приоритета и так далее в порядке убывания приоритета. Операции одного уровня приоритета выполняются в последовательности, указанной их порядком.
Операции, уровень приоритета которых равен 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 - указатель на структуру. Оператор:
www.intuit.ru/studies/professional_skill_improvements/1747/courses/43/print_lecture/655 |
5/16 |
07.06.13 |
Операции |
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;
www.intuit.ru/studies/professional_skill_improvements/1747/courses/43/print_lecture/655 |
6/16 |
07.06.13 |
Операции |
Дополнение до единицы значения |
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
www.intuit.ru/studies/professional_skill_improvements/1747/courses/43/print_lecture/655 |
7/16 |
07.06.13 |
Операции |
Тип операнда - значение любого типа или имени типа. Тип результата - 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. Выполняются эти операции слева направо.
Операция сложения: +
Тип операндов:
1.арифметический;
2.один операнд указатель, другой - интегрального типа; оба операнда не могут быть указателями.
Тип результата: int, unsigned, long, double, указатель. Перед сложением значение целого операнда умножается на величину элемента данных, тип которых соответствует типу указателя.
www.intuit.ru/studies/professional_skill_improvements/1747/courses/43/print_lecture/655 |
8/16 |
07.06.13 |
Операции |
Использование:
ae1+ae2
Сумма значений ae1 и ae2.
Пример 1:
i=i+100;
Первоначальное значение i увеличивает на 100.
Пример 2:
last=arname+arsize-1;
Присваивает переменной last адрес последнего элемента массива arname.
Операция вычитания: -
Тип операндов:
1.арифметический;
2.один операнд - указатель, другой - интегрального типа;
3.операнды - указатели одного типа.
Впервом случае тип результата: 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.
www.intuit.ru/studies/professional_skill_improvements/1747/courses/43/print_lecture/655 |
9/16 |
07.06.13 |
Операции |
Пример 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
www.intuit.ru/studies/professional_skill_improvements/1747/courses/43/print_lecture/655 |
10/16 |