Вторник, 21.05.2024, 09:10
Приветствую Вас, Гость

БИЛЕТ 22.

1) Старшинство и порядок выполнения операций

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

Примеры.

1) a=f()+g()

Если функции f и g используют глобальные переменные и меняют их, то результат a будет зависеть от того, в каком порядке они будут вызваны.

2) f(v[i], i++);

порядок вычисления аргументов неопределен.

3) a/(b*d)

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

Рекомендации:

1) уровень старшинства побитовых операций & ^ || ниже, чем уровень операции == и !=. В условиях, осуществляющих побитовую проверку, выражения должны заключаться в скобки.

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

a=f();

b=g();

c=a+b;

Все логические операции младше арифметических, поэтому скобки могут опускаться. a*b+c<3

 Логические связки && || вычисляются слева направо с учетом приоритета скобок. При это их рассмотрение прекращается сразу же, как только становится ясно будет ли результат истинным или ложным.

Старшинство операций  сравнения == и != выше, чем у операции присваивания, которая имеет один из самых низких приоритетов.

Название

Символ операции

Порядок выполнения

Обращение к функции

Выделение элемента массива

Выделение поля структурной переменной

Выделение поля структурной переменной по указателю на ее начало

( )

[ ]

.

->

Слева направо

То же

То же

То же

 

Логическое отрицание

Поразрядное логическое НЕ

Изменение знака (унарный минус)

Инкремент

Декремент

Определение адреса переменной

Обращение к памяти по значению указателя

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

Определение размера в байтах

!

~

-

++

--

&

*

(type)

sizeof

Справа налево

То же

То же

То же

То же

То же

То же

То же

То же

Умножение

Деление

Определение остатка целого деления

*

/

%

Слева направо

То же

То же

Сложение

Вычитание

+

-

Слева направо

То же

Сдвиг влево

Сдвиг вправо

<< 

>> 

Слева направо

То же

Меньше

Меньше или равно

Больше

Больше или равно

<=

>=

Слева направо

То же

То же

То же

Равно

Не равно

= =

!=

Слева направо

То же

Поразрядное логическое И

&

Слева направо

Поразрядное исключающее ИЛИ (XOR)

^

Слева направо

Поразрядное логическое ИЛИ

|

Слева направо

Логическое И

&&

Слева направо

Логическое ИЛИ

||

Слева направо

Операция условия

?:

Справа налево

Присваивание

= += -+ *= /= %= <<= >>= |= ^= &=

Справа налево

Операция «запятая»

,

Слева направо

 

 

2) Директивы препроцессора.

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

Директивы препроцессора:

#include

#define

#undef

#if

#else

#endif

#ifdef  (#if defined)

#ifndef (#if !defined)

#error

#line

#pragma

Директива #include

Строка

#include "имя. файла "

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

Строка

#include <имя. файла>

ищет файл только в директории заданной в опциях компилятора.

Директива #define

#define идентификатор строка символов

заменяет все последующие вхождения идентификатора строкой символов.

пример:

#define A_NUMBER 100

int n=A_NUMBER ;

n присвоится значение 100

 

#define можно применять также для определения макросов,например

#define SWAP(a,b) temp=(a);(a)=(b);(b)=temp

подробнее о #define (и в частности о макросах) будет отдельная статья

Директива #undef

строка

#undef идентификатор

отменяет прероцессорное определение идентификатора

Директивы #if #else #endif

директива

#if выражение

.....

#endif

проверяет истинно ли выражение и если истинно, то выполняет все последующие строки до директивы #endif

 

конструкция типа

#if выражение

....

#else

...

#endif

проверяет выражение, если оно истинно то выполняются строки между #if и #else а если ложно то между #else и #endif

Директивы #ifdef #ifndef

директива  #ifdef идентификатор

.....

#endif

проверяет определен ли идентификатор в препроцессоре в данный момент(директивой #define) и если определен, то выполняет все последующие строки до директивы #endif

директива  #ifndef идентификатор

.....

#endif

наоборот, выполняет все последующие строки до директивы #endif если идентификатор не определен в препроцессоре в данный момент

Директива #error

Директива  #error сообщение об ошибке

останавливает работу компилятора и выдает сообщение об ошибке .

Директива #line

Директива #line константа "имя. файла”

заставляет компилятор считать, что константа задает номер следующей строки исходного файла, и текущий входной файл именуется идентификатором. Если идентификатор отсутствует, то запомненное имя файла не изменяется.

Директива #pragma

#pragma - это директива препроцессора, которая реализует возможности компилятора. Эти особенности могут быть связанны с типом компилятора.Разные типы компиляторов могут поддерживать разные директивы. Общий вид директивы:

#pragma команда компилятора


*************************************22 - 3

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

 

#include<stdio.h>

#include<conio.h>

int day1=18,mon1=2,year1=1977;

int day2=19,mon2=3,year2=1977;

int d_rez,m_rez,y_rez,more,i;

void main()

{

 clrscr();

 y_rez = year2 - year1;

 if (y_rez == 0)

     m_rez = mon2 - mon1;

 else

     m_rez = 12 - mon1 + mon2;

 if (m_rez == 0)

     d_rez = day1 + day2 - 1;

 else

    {

     if (mon1 == 1 || mon1 == 3 || mon1 == 5 ||mon1 == 7 || mon1 == 8 || mon1 == 10 || mon1 == 12)

             d_rez = 31 - day1 + day2;

     else

             d_rez = 30 - day1 + day2;

    }

 if (d_rez >= 30)

    {

     if (mon1 == 1 || mon1 == 3 || mon1 == 5 ||mon1 == 7 || mon1 == 8 || mon1 == 10 || mon1 == 12)

            {

             d_rez -= 31;

             more = d_rez/m_rez;

            }

     else

            {

             d_rez -= 30;

             more = d_rez%m_rez;  //HERE

            }

     if (more == 0)

             more = 1;

     m_rez += more;

    }

 while (m_rez >= 12)

       {

            m_rez -= 12;

            y_rez += 1;

       }

 m_rez -= 1;

 if (y_rez > 0)

     y_rez -= 1;

 for (i=year1;i<year2;i++)

 if((i%4 == 0) && (i%100 != 0))

     d_rez++;

 if((mon1<=2)&(mon2>=2))

    d_rez -= 2*y_rez;

 if (d_rez < 0)

     for(i=0;d_rez<0;i++)

            {

             d_rez += 30;

             y_rez++;

            }

 

 printf("%d days, %d month(es) and %d year(s) latter...",d_rez,m_rez,y_rez);

 getch();

}

 

*************************************22 - 4

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

 

#include<stdio.h>

#include<conio.h>

#include<string.h>

void main()

{

char*a;

do{

   printf("Enter symbol");

  gets(a);

      printf("%d ",*a);

   printf("\n");

}while(*a!='.');

getch();

}