Рассмотрим способы обработки данных - для этого язык Си имеет широкий набор возможностей. Основные арифметические операции: сложения, вычитания, умножения, деления. Операции в языке Си применяются для представления арифметических действий. Например, выполнение операции + приводит к сложению двух величин, стоящих слева и справа от этого знака. Рассмотрим операции =, +, -, *, /. В языке Си нет операции возведения в степень.
В языке Си знак равенства не означает "равно". Он означает
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:
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.
Унарные операции. Для унарных операций требуется только один 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");
Тип 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--;
Тип unsigned. Используется как sizeof (выражение) или sizeof (имя типа).
Пример:
n=sizeof(arname)/sizeof(int);
Число элементов в массиве целых чисел, определяемое как число байт в массиве, поделенное на число байт, занимаемых одним элементом массива.
Мультипликативные операции. Порядок выполнения мультипликативных операций - слева направо.
Тип 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. Выполняются эти операции слева направо.
Тип
Тип результата: 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. Порядок выполнения операций - слева направо.
Тип int. Левый
Использование:
ie1<<ie2
Двоичное представление ie1 сдвигается влево на ie2 разрядов, освобождающие разряды заполняются нулями.
Пример:
four=x<<2;
Тип int. Левый unsigned.
Использование:
ie1>>ie2
Двоичное представление ie1 сдвигается вправо на ie2 разрядов. Сдвиг вправо может быть арифметическим (т. е. освобождающиеся слева разряды заполняются значениями знакового разряда) или логическим в зависимости от реализации, однако гарантируется, что сдвиг вправо целых чисел без знака будет логическим и освобождающиеся слева разряды будут заполняться нулями.
Пример:
x=x>>3;
Уровень приоритета операций отношения равен 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, выполняются они слева направо.
Тип int.
Использование:
ie1==ie2
Истина, если ie1 равно ie2, иначе - ложь.
Тип int.
Единственным целым значением, с которым можно сравнивать указатели, является нулевое значение!
Использование:
ie1!=ie2
Истина, если ie1 не равно ie2.
Пример:
while (i!=0) i=func;
Уровень приоритета операции поразрядное И равен 8. Выполняются такие операции слева направо.
Тип int, long, unsigned.
Использование:
ie1 ie2
Побитовая операция И двоичных представлений ie1 и ie2. Значение выражения содержит 1 во всех разрядах, в которых и ie1 и ie2 содержат 1, и 0 во всех остальных разрядах.
Пример:
flag=((xmask)!=0);
Уровень приоритета операции поразрядное исключающее ИЛИ равен 9. Порядок выполнения таких операций слева направо.
Тип int, long, unsigned.
Использование:
ie1^ie2
Побитовая операция исключающее ИЛИ двоичных представлений ie1 и ie2. Значение выражения содержит 1 в тех разрядах, в которых и ie1 и ie2 имеют разные двоичные значения, и 0 во всех остальных разрядах.
Пример:
diffbits=x^y;
Уровень приоритета операции поразрядное включающее ИЛИ равен 10, порядок выполнения таких операторов - слева направо.
Тип int, long, unsigned.
Использование:
ie1 | ie2
Побитовая операция ИЛИ двоичных представлений ie1 и ie2. Значение выражения содержит 1 во всех разрядах, в которых ie1 или ie2 содержат 1, и 0 во всех остальных разрядах.
Пример:
attrsum=attr1 | attr2;
Уровень приоритета логической (условной) операции и равен 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, выполняются такие операции слева направо.
Тип int. Если хотя бы один 0, результат равен 1 ; иначе результат будет равен 0.
Использование:
e1 || e2
Логическая операция ИЛИ значений e1 и e2. Вначале проверяется значение e1 ; значение e2 проверяется только в том случае, если значение e1 - ложь. Значением выражения является Истина, если истинно любое значение e1 или e2.
Пример 1:
if(x<A || x>B) printf("out of range");
Уровень приоритета операции равен 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, выполняются такие операции справа налево.
Тип
Использование:
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 <знак> 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, выполняются такие операции слева направо.
Тип результата совпадает с типом правого
Использование:
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:
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.
Унарные операции. Для унарных операций требуется только один 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");
Тип 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--;
Тип unsigned. Используется как sizeof (выражение) или sizeof (имя типа).
Пример:
n=sizeof(arname)/sizeof(int);
Число элементов в массиве целых чисел, определяемое как число байт в массиве, поделенное на число байт, занимаемых одним элементом массива.
Мультипликативные операции. Порядок выполнения мультипликативных операций - слева направо.
Тип 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. Выполняются эти операции слева направо.
Тип
Тип результата: 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. Порядок выполнения операций - слева направо.
Тип int. Левый
Использование:
ie1<<ie2
Двоичное представление ie1 сдвигается влево на ie2 разрядов, освобождающие разряды заполняются нулями.
Пример:
four=x<<2;
Тип int. Левый unsigned.
Использование:
ie1>>ie2
Двоичное представление ie1 сдвигается вправо на ie2 разрядов. Сдвиг вправо может быть арифметическим (т. е. освобождающиеся слева разряды заполняются значениями знакового разряда) или логическим в зависимости от реализации, однако гарантируется, что сдвиг вправо целых чисел без знака будет логическим и освобождающиеся слева разряды будут заполняться нулями.
Пример:
x=x>>3;
Уровень приоритета операций отношения равен 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, выполняются они слева направо.
Тип int.
Использование:
ie1==ie2
Истина, если ie1 равно ie2, иначе - ложь.
Тип int.
Единственным целым значением, с которым можно сравнивать указатели, является нулевое значение!
Использование:
ie1!=ie2
Истина, если ie1 не равно ie2.
Пример:
while (i!=0) i=func;
Уровень приоритета операции поразрядное И равен 8. Выполняются такие операции слева направо.
Тип int, long, unsigned.
Использование:
ie1 ie2
Побитовая операция И двоичных представлений ie1 и ie2. Значение выражения содержит 1 во всех разрядах, в которых и ie1 и ie2 содержат 1, и 0 во всех остальных разрядах.
Пример:
flag=((xmask)!=0);
Уровень приоритета операции поразрядное исключающее ИЛИ равен 9. Порядок выполнения таких операций слева направо.
Тип int, long, unsigned.
Использование:
ie1^ie2
Побитовая операция исключающее ИЛИ двоичных представлений ie1 и ie2. Значение выражения содержит 1 в тех разрядах, в которых и ie1 и ie2 имеют разные двоичные значения, и 0 во всех остальных разрядах.
Пример:
diffbits=x^y;
Уровень приоритета операции поразрядное включающее ИЛИ равен 10, порядок выполнения таких операторов - слева направо.
Тип int, long, unsigned.
Использование:
ie1 | ie2
Побитовая операция ИЛИ двоичных представлений ie1 и ie2. Значение выражения содержит 1 во всех разрядах, в которых ie1 или ie2 содержат 1, и 0 во всех остальных разрядах.
Пример:
attrsum=attr1 | attr2;
Уровень приоритета логической (условной) операции и равен 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, выполняются такие операции слева направо.
Тип int. Если хотя бы один 0, результат равен 1 ; иначе результат будет равен 0.
Использование:
e1 || e2
Логическая операция ИЛИ значений e1 и e2. Вначале проверяется значение e1 ; значение e2 проверяется только в том случае, если значение e1 - ложь. Значением выражения является Истина, если истинно любое значение e1 или e2.
Пример 1:
if(x<A || x>B) printf("out of range");
Уровень приоритета операции равен 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, выполняются такие операции справа налево.
Тип
Использование:
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 <знак> 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, выполняются такие операции слева направо.
Тип результата совпадает с типом правого
Использование:
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);
}
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.