Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конспект лекций по курсу 'Информатика'.doc
Скачиваний:
11
Добавлен:
14.07.2019
Размер:
483.84 Кб
Скачать

Директива препроцессора #define .

Мы уже сталкивались с директивами препроцессору #include для включения информации из другого файла в программу. При помощи директивы препроцессора #define можно задавать константы.

#define PI 3.14

При компиляции программы каждый раз вместо PI будет подставлено ее значение. Знак ; не ставится, т.к. это не оператор языка С. Использовать эту директиву можно для любых констант, даже для звукового сигнала ‘007’, и признака конца -‘\0’.

#define BEEP ‘007’

#define NULL ‘\0’

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

Могут быть и такие макроопределения:

#define FMT “ x %d \n”

далее в программе к нему обращаются так:

printf (FMT, x ) ;

Макроопределения еще их называют - макросамиэто текстовые подстановки, происходящие до компиляции программы. Вы заметили, что все макросы пишутся с большой буквы – это договоренность между программистами. Если видишь, что-либо написанное с большой буквы, ищи определение объекта как макроса в директиве препроцессора #define.

Хотя это требование не правило, если вы напишите с маленькой буквы, все будет работать.

Могут быть макроопределения и с параметрами:

#define SQR ( X ) X*X

далее в программе к нему обращаются так:

x=4 ; y=12 ;

z1= SQR(x) ;

z2= SQR(y) ;

Могут быть и более сложные условные макросы:

#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))

#define ABS (X) ( X < 0) ? -(X) : (X))

далее в программе к ним обращаются так:

y=2*MAX(a+b , r+c ) ;

z= ABS ((x-y)/2.) ;

Области видимости.

Рассмотрим программу из двух функций:

#include …

void func (int *a, float b) // в скобках формальные параметры

{ int x, y ; // локальные переменные

}

main()

{

int x, y, z ; // y и z локальные переменные

float b ;

func(&x, b) ; // в скобках фактические параметры

}

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

Сделаем переменную b из предыдущего примера глобальной.

#include …

float b ; // описание глобальной переменной

void func (int *a ) // в скобках формальные параметры

{ int x, y ; // локальные переменные

x=b ; // использование глобальной переменной

}

main()

{

int x, y, z ; // y и z локальные переменные

b++ ; // использование глобальной переменной

func(&x ) ; // в скобках фактические параметры

}

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

Классы памяти.

Каждая переменная имеет тип, кроме того каждая переменная принадлежит к некоторому классу памяти. До использования подпрограмм мы не задумывались об этом, т.к. пользовались всегда одним классом памяти – автоматическим. Вообще существует 4 класса памяти.

extern

Внешний

auto

Автоматический

static

Статический

register

регистровый

Классы памяти позволяют определить:

- какие функции имеют доступ к каким переменным, т.е. определяют области

видимости;

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

Рассмотрим каждый класс памяти.

Auto

По умолчанию все переменные, описанные внутри функции, являются автоматическими. Эти переменные локальные.

main()

{

int x, y ; одно и то же auto int x, y ;

}

Аuto иногда пишут специально, чтобы не искать описание объектов вне функции.

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

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

Exetrn

int a ;

main()

{ extern int a ; // a – внешняя, глобальная переменная.

x=a*b ;

}

Будет то же самое, если вообще не описывать переменную а в main, но когда явно описано, что переменная extern, то понятно, что она глобальная и описана выше.

Внешние переменные известны всем функциям, и не исчезнут, пока не закончит работу вся программа.

Static

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

Рассмотрим простой пример иллюстрирующий работу статической переменной.

main()

{ int i ;

for ( i=1 ; i<=3 ; i++)

{ printf (“ i=%d\n”, i) ;

ff() ;

}

}

void ff(void)

{ int a=1 ;

static int b=1 ;

printf(“a=%d b=%d\n”, a++, b++) ;

}

печать результатов будет такой:

i=1

a=1 b=1

i=2

a=1 b=2

i=3

a=1 b=3

Автоматическая переменная а при каждом вызове инициализируется заново, а статическая переменная b только при первом вызове функции. Такие переменные удобно использовать, когда нужно накапливать сумму при многократном обращении к подпрограмме.

Могут быть и внешние статические переменные.

register

Регистровые переменные хранятся на регистрах центрального процессора, где доступ и работа с ними быстрее, чем в памяти. С такими переменными мы работать не будем.

Рекомендация: старайтесь использовать автоматические переменные и передавать информацию в

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

порождает большие ошибки.