Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Приоритет операций и порядок выполнения (ассоциативность)

Поиск

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

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

Таблица 6.2 - Приоритет операций

Приоритет Знак операции Тип операции Ассоциативность (порядок выполнения)
  () [ ].–> Первичные → слева направо
  – ~! * & ++ -- sizeof, приведение типов () Унарные ← справа налево
  * / % Мультипликативные
  + - Аддитивные
  << >> Сдвиги
  < > <= > = Отношение
  = =! = Отношение
  & Поразрядное "и"
  ^ Поразрядное исключающее "или"
  | Поразрядное включающее "или"
  && Логическое "и"

 

 

Продолжение таблицы 6.2

Приоритет Знак операции Тип операции Ассоциативность (порядок выполнения)
  | | Логическое "или"
  ?: Условная (тернарная)
  = * = / = % = Простое и составное присваивание
+ = – = << = >> =
& = | = ^ =  
  , Последовательное вычисление

 

Если несколько операций одного приоритета встречаются в выражении, то они применяются в соответствии с ассоциативностью.

Примеры. а = b&ÆхFF + 5; // вычисляется как а = b&(Æх FF + 5);

b=а + с >> 1; // как b=(а +с) >> 1;

с = а + + + b/5; // как с=(а + +) + (b/5);

Мультипликативные, аддитивные и поразрядные операции обладают свойством коммутативности. Компилятор вычисляет выражения с учётом приоритета в любом порядке, даже если есть скобки. Определённый порядок вычисления (,) операндов гарантируют операции: последовательного вычисления, логические «И» (&&) и «ИЛИ» (||), условная операция (?:).

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

func (i + 1, i = j + 2); //. Не гарантирует порядок вычисления фактических

// аргументов

i= 0; // i имеет тип int по умолчанию

a [++ i] = i; // порядок вычисления левого и правого операндов не
// гарантируются a [0] = 0 или a[1]=1

(x - 5) && ++ i // Если x =5, то ++ i не вычисляется

int x, y, z, f();

z = x > y || f(x, y); // Если x > y, то значение z = 1 «Истина», а f() –не

// вызывается

// если x £ y, то f() вызывается, тогда z=0,

// eсли f() возвращает нулевое значение, или z = 1,

// если f() возвращает не нулевое значение

// printf (“%d %d \n“, ++n, p()2, n)

// в функцию может передаваться n или n+1.

 

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

В выражениях С переменные различных типов в ряде случаев могут использоваться совместно; например, переменные типа char могут присутствовать в выражениях одновременно с переменными типа int.

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

char ch='a', ans; // объявление переменных ch и ans

printf("значение ch + 3 = %d", ch+3); // вывод значения ch+3

ans = ch % 3; // определение остатка от целочисленного деления

printf("\n\n значение ans = % d\n", ans);

Поскольку char это целый тип, для него применимы все операции, операнды которых могут иметь тип int. Целые по умолчанию - это величины со знаком signed.

С переменными вещественного типа (float, double и др.) применимы все операции, допустимые для целого типа int, за исключением операции остатка от деления (%).

Преобразования типов бывают явные и неявные. Синтаксис операции явного преобразования типа

(<новый_тип>) <операнд>

или

<новый_тип> (<операнд>).

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

Рассмотрим результаты таких преобразований.

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

Арифметические операции над числами с плавающей точкой (float и double) по умолчанию выполняются с двойной точностью.

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

Если целое без знака (unsigned) используется вместе с простым целым, то простое целое и результат преобразуются в целое без знака.

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

Сначала любые операнды типов char, unsigned char или short преобразуются в int, а любые операнды типа float преобразуются в double.

Затем, если какой-либо операнд имеет тип double, то другой преобразуется к типу double и типом результата будет double.

В случае, если какой-либо операнд имеет тип unsigned long, то другой преобразуется к типу unsigned long и это же будет и типом результата.

В случае, если какой-либо операнд имеет тип long, то другой преобразуется к типу long и это же будет типом результата.

В случае, если операнд имеет тип unsigned, то другой операнд преобразуется к типу unsigned, и это будет типом результата.

Объект типа void* ( указатель на пустой ) может быть объявлен для указания на объекты неизвестного типа.

Преобразование типа такого указателя задаётся с помощью явной операции преобразования типов.

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

Указатель на один тип может быть преобразован в указатель на другой тип. При этом возможно преобразование указателя в указатель на объект меньшего размера и обратно без изменений.

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

 

extern void* allos ();

doube* dp;

dp = (doube*) allos (sizeof (doube));

*dp = 2,6/8,4

Пример

#include <stdio.h>

#include <conio.h>

#include <math.h>

main()

{float r1,r2;

int a,b,b1;

unsigned c,d;

char e,f;

unsigned char g;

float f1,f2;

clrscr();

printf("ввод первого u второго вещественных чисел: ");

scanf("%f %f",&r1,&r2);

//printf("\n");

printf("вывод результатов операций для чисел: %5.2f %5.2f\n",r1,r2);

printf("!r1= %d ",!r1); printf("!r2= %d ",!r2);

printf("r1>r2 %d ",r1>r2); printf("r1<r2 %d\n",r1<r2);

printf("r1||r2 %d ",r1||r2); printf("r1&&r2 %d ",r1&&r2);

printf("r1==r2 %d ",r1==r2); printf("r1>=r2 %d\n",r1>=r2);

printf("r1<=r2 %d ",r1<=r2); printf("r1!=r2 %d\n",r1!=r2);

//Вложенный блок, переменные переобъявлены: int r1,r2; float b;

{int r1,r2;

float b;

printf("ввод первого u второго целого числа: ");

scanf("%d %d",&r1,&r2);

// printf("\n");

printf("вывод результатов операций для целых чисел: %2d %2d\n",r1,r2);

printf("!r1= %d ",!r1); printf("!r2= %d ",!r2);

printf("r1>r2 %d ",r1>r2); printf("r1<r2 %d\n",r1<r2);

printf("r1||r2 %d ",r1||r2); printf("r1&&r2 %d ",r1&&r2);

printf("r1==r2 %d ",r1==r2); printf("r1>=r2 %d\n",r1>=r2);

printf("r1<=r2 %d ",r1<=r2); printf("r1!=r2 %d ",r1!=r2);

printf("~r1 %d ",~r1); printf("r1|r2 %d\n",r1|r2);

printf("r1^r2 %d ",r1^r2); printf("r1&r2 %d ",r1&r2);

printf("r1<<r2 %d ",r1<<r2); printf("r1>>r2 %d\n",r1>>r2);

 

printf("Исходные значения: r1=%d r2=%d\n",r1,r2);

r2=r1++; //Постфиксные операции а1++ а1--

printf("r2=r1++; r1=%d r2=%d\n",r1,r2);

--r1; r2=++r1; //Префиксные операции ++а1 --а1

printf("--r1; r2=++r1; r1=%d r2=%d\n",r1,r2);

r1-=4; r2+=5; //Составное присваивание

printf("r1-=4; r2+=5; r1=%d r2=%d\n",r1,r2);

a=r2-=2,r1+=5; //Составное присваивание

printf("a=r2-=2,r1+=5; r1=%d r2=%d a=%d\n",r1,r2,a);

a=(r1<r2)?r1:r2;//Тернарная операция если r1<r2, то а=r1 иначе а=r2

printf("a=(r1<r2)?r1:r2; a=%d\n",a);

a=r2%r1; //Остаток от деления целых

printf("а=r1%r2; "); printf("а=%d\n",r2%r1);

a=r2/r1; //Деление целых

printf("a=r2/r1; a=%d\n",a);

b=(float)r2/(float)r1; //Деление c преобразованием типов

printf("b=(float)r2/(float)r1; b=%f\n",b);

}

float q=1.3,q1=2.4,raz;

printf("Введите переменные a-(int), \

c-(unsigned), g-(unsigned char)\n");

scanf("%i,%u,%uc",&a,&c,&g);

b = (a & (c<<3));

b1 = (a & 3) << 7;

f = (a & 3) << 7;

f1 = q / (c | 0x3E);

f2 = a / (c | 0x3E);

raz=exp(q+q1)/4;

printf("g=%u, q=%5.2f, q1=%7.2f, b=%i, b1=%i, \

\n",g,q,q1,b,b1);

printf("f=%i, f1=%6.3f, f2=%6.3f, raz=%f\n",f,f1,f2,raz);

getch(); return 0;

}

/* ввод первого u второго вещественных чисел: 56 7

вывод результатов операций для чисел: 56.00 7.00

!r1= 0!r2= 0 r1>r2 1 r1<r2 0

r1||r2 1 r1&&r2 1 r1==r2 0 r1>=r2 1

r1<=r2 0 r1!=r2 1

ввод первого u второго целого числа: 45 2

вывод результатов операций для целых чисел: 45 2

!r1= 0!r2= 0 r1>r2 1 r1<r2 0

r1||r2 1 r1&&r2 1 r1==r2 0 r1>=r2 1

r1<=r2 0 r1!=r2 1 ~r1 -46 r1|r2 47

r1^r2 47 r1&r2 0 r1<<r2 180 r1>>r2 11

Исходные значения: r1=45 r2=2

r2=r1++; r1=46 r2=45

--r1; r2=++r1; r1=46 r2=46

r1-=4; r2+=5; r1=42 r2=51

a=r2-=2,r1+=5; r1=47 r2=49 a=49

a=(r1<r2)?r1:r2; a=47

а=r1%r2; а=2

a=r2/r1; a=1

b=(float)r2/(float)r1; b=1.042553

Введите переменные a-(int), c-(unsigned), g-(unsigned char)

-34 6 7

g=122, q =1.30, q1=2.40, b=512, b1=256,

f=0, f1=0.010, f2=519.000, raz=10.111827 */

Ход работы

1 Изучить теоретические сведения.

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

3 Ознакомившись с приоритетом операций, показать порядок выполнения операций в конкретных выражениях с использованием скобок.

4 Для преобразования типов переменных использовать явное и неявное преобразование типов.

5 Разработать алгоритм и программу, отладить ее на компьютере.

6 Изучить выполнение операций и тип результата.

7 Получить результаты и сделать выводы по работе.

8 Оформить отчет.

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

 

Требования к содержанию отчёта приведены в лабораторной работе №1.

 

Индивидуальное задание к лабораторной работе №6.

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

Таблица 6.3 - Индивидуальные задания

вариант арифметическая операция арифметическая операция логическая операция битовая операция преобразование: явное
  (a + b)*с (c/ab) чётное a << = b int®short
  (a*b)-с a|=b-c нечётное a >> = b long®int
  (a / b)+++b a<<=b/c (a==c)&& (b<a) a^=b signed®unsigned
  ++b-(~a) a%=b a > b a%=b+c double®float
  (a+b)* sizeof(c) (a+b)1/c a < b a>>=5 int®char
  --c*(*&a+b) (a+b)/5 a>=b a&=abs(c) long double ®double
  A2+b2+c2 15ab-(1/4c) a!=b a<<=6 float ®long
  5b3-2a+c c2+8b+10a a||b a&=b+c float®char
  4a2+5b2 3a2+4b-8 a&&b a^=b double®int
  3ab-4c A3+b2-8c !a a%=(c+10) double®unsigned long int
  c2+5a3-b A2+b2-6c (a<b)|| (c>5) a|=20   float®unsigned
  2a+4c-b4 A+2b+3c a>=b a&=(b+c) int®char
  A2+b2 2(a+b)-c4 (a>=b)|| (b<c) a^=abs(b-c) long double ®double
  (a+b)2 c2-b3 кратное а (a&b)^c double®float
  2ac-3cb 3a-4cb (c!=b)|| (a==10) (a|b)>>c double®unsigned long int
  5c+2a4 c5-2ab (c<=a)&&(b!=a) (b&&c)|(a--) signed®unsigned
  A+b+c 6a+3b3+c (b==0)|| (c<=a) a|=b+c int®short
  2a+3b+4c 4abc (a==1)|| (b<c) a|= (c+10) double®int
  A2+b3+c4 A2+(b-c)5/3 (a<b)&& (a>c) a|=20   double®float
  A+2b+3c (a+4b)1/3-c2 (a>=b)|| (a<=10) (a&b)^c int®char
  2(a+b)-c4 A1/3+(b3-c) (b<c)&& (b!=a) a|=b+c long double ®double
  c2-b3 B3+(a-4c)1/5 (b<c)|| (a<b) a&=b+c double®float
  3a-4cb A+2b+3c (a==1)&&(c!=0) a&=abs(c-b) int®char
  c5-2ab 2(a+b)-c4 (c==0)|| (b!=100) a%=b+c long double ®double
  6a+3b3+c c2-b3 (b!=0)&& (b<c) (a&b)^c int®char
  4abc 3a-4cb (b!=a)|| (b<=c) a%=b+c long double ®double
  A2+(b-c)5/3 c5-2ab (c<=12)&&(c>=24) (b|c)|(a--) double®unsigned long int
  (a+4b)1/3-c2 6a+3b3+c ((a-b)<c)|| ((a*c) <100) a<<=6 float®unsigned
  A1/3+(b3-c) 4abc (a<10)? (b):(b-c) (b&c)|(a--) int®char
  B3+(a-4c)1/5 A2+(b-c)5/3 (b<=10)|| ((a+b)< (b-c)) a^=abs(b-c) long double ®double

 

Контрольные вопросы для подготовки и самостоятельной работы

1 Какие операции называются унарными, бинарными, тернарными?

2 Сколько групп приоритетов принято в С?

3 В какой последовательности выполняются операции с одинаковым приоритетом?

4 Что означает свойство коммутативности?

5 Какие операции гарантируют порядок вычисления своих операндов?

6 Для чего применяют первичные операции?

7 Какой тип операндов допустим для различных операций?

8 Все ли операнды вычисляются в выражениях, содержащих логические операции?

9 Для чего применяют преобразование типов?

10 Назовите правила неявного преобразования типов. В каких случаях возможна потеря информации при преобразовании типов?

11 В каком порядке будет выполняться конструкция f(x)&&g(y) и как будет интерпретироваться результат вызова функций, результат выражения в целом?

12 Объясните примеры, приведенные в теоретической части.

Лабораторная работа №7

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

(2 часа)

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

Теоретические сведения

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



Поделиться:


Последнее изменение этой страницы: 2016-04-26; просмотров: 683; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.119.137.175 (0.008 с.)