Приоритет операций и порядок выполнения (ассоциативность)
Приоритет и ассоциативность операций влияют на порядок группирования операндов и порядок вычислений в выражениях С. Например, приоритет выполнения операций необходимо учитывать при составлении сложных арифметических формул. Операции, приведенные в одной группе таблицы, имеют одинаковый приоритет и ассоциативность. Порядок убывания приоритета сверху вниз. Таблица 20 - Приоритет операций
Если несколько операций одного приоритета встречаются в выражении, то они применяются в соответствии с ассоциативностью. Примеры. а = 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; // порядок вычисления левого и правого операндов не (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 Пример 17 #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 Подготовиться к защите лабораторной работы, изучив вопросы по данной теме.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|