Классы памяти. Препроцессор Алтайский государственный университет

Содержание

Слайд 2

План Лекция 9 План Классы памяти переменных Препроцессор

План

Лекция 9

План
Классы памяти переменных
Препроцессор

Слайд 3

Классы памяти переменных Автоматический класс Статический класс Регистровый класс Внешний класс

Классы памяти переменных

Автоматический класс
Статический класс
Регистровый класс
Внешний класс
Внешний статический класс
Изменяемость переменных
Общая схема

описания переменных
Слайд 4

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

Классы памяти переменных

Классы памяти переменных

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

время жизни переменной
В языке Си переменные могут иметь один из следующих классов памяти:
auto – автоматический
static – статический
extern – внешний
register – регистровый
внешний статический
Слайд 5

Классы памяти переменных Классы памяти переменных Автоматический класс памяти (auto) задается

Классы памяти переменных

Классы памяти переменных

Автоматический класс памяти (auto)
задается необязательным ключевым словом

auto при описании переменной перед указанием типа
auto float f=0;
время существования переменной определяется областью видимости
переменная создается в начале блока {…}
переменная удаляется в конце блока {…}
при инициализации переменных допускается употребление выражений, включающих переменные и вызовы функций
auto float a=10, b=2*a*sqrt(a);
Слайд 6

Классы памяти переменных Классы памяти переменных Автоматический класс памяти (auto) задается

Классы памяти переменных

Классы памяти переменных

Автоматический класс памяти (auto)
задается необязательным ключевым словом

auto при описании переменной перед указанием типа
область действия существования переменной определяется областью видимости

void main() {
auto int i;
for (i=0; i<5; ++i) {
int k=100;
if(i%2) {
int d = 3;
   k-=d;
}
k++;
}
}  
Область видимости i

Создание i в памяти

Инициализация i

Использование i

Удаление i

Слайд 7

Классы памяти переменных Классы памяти переменных void main() { auto int

Классы памяти переменных

Классы памяти переменных

void main() {
auto int i;

for (i=0; i<5; ++i) {
int k=100;
if(i%2) {
int d = 3;
   k-=d;
}
k++;
}
}  

Создание k в памяти

Инициализация k

Использование k

Удаление k
Область видимости k

Автоматический класс памяти (auto)
задается необязательным ключевым словом auto при описании переменной перед указанием типа
время существования переменной определяется областью видимости

Слайд 8

Классы памяти переменных Классы памяти переменных void main() { auto int

Классы памяти переменных

Классы памяти переменных

void main() {
auto int i;

for (i=0; i<5; ++i) {
int k=100;
if(i%2) {
int d = 3;
   k-=d;
}
k++;
}
}  

Создание d в памяти

Инициализация d

Использование d

Удаление d
Область видимости d

Автоматический класс памяти (auto)
задается необязательным ключевым словом auto при описании переменной перед указанием типа
время существования переменной определяется областью видимости

Слайд 9

Классы памяти переменных Классы памяти переменных Автоматический класс памяти auto #include

Классы памяти переменных

Классы памяти переменных

Автоматический класс памяти auto

#include
void func(int p) {


auto int a = 2; /* автоматическая переменная */
int b = sqrt(a); /* автоматическая переменная */
b += 2*a + p;   
printf(“a = %d, b = %d\n“, a, b);
}
void main() {
int i; /* автоматическая переменная */
for (i=0; i<5; ++i)
if(i%2) {
int d = 13; /* автоматическая переменная */
func(i+d);   
}
}

Создание a,b в памяти

Инициализация a,b

Использование a,b

Удаление a,b

Слайд 10

Классы памяти переменных Классы памяти переменных Статический класс памяти (static) задается

Классы памяти переменных

Классы памяти переменных

Статический класс памяти (static)
задается ключевым словом static

при описании переменной перед указанием типа
static int a=0;
область видимости переменной – блок {…}, в котором она определена
время существования переменной – сеанс работы программы
переменная создается при старте программы
переменная удаляется при завершении программы
инициализация переменных осуществляется только при первом входе в блок
static int a=0; /* инициализация однократна, */ /* между входами в блок */ /* значение переменной сохраняется */
параметры функций не могут быть статическими
Слайд 11

Классы памяти переменных Классы памяти переменных Пример. Автоматическая и статическая переменные

Классы памяти переменных

Классы памяти переменных

Пример. Автоматическая и статическая переменные

#include
void stat();

/* прототип функции */
void main() {
int i;
for (i=0;i<5;++i) stat();   
}
void stat() {
int a = 0; /* автоматическая переменная */
static int s = 0; /* статическая переменная */ 
printf(“auto = %d, static = %d\n“, a, s);
++a; ++s;   
}

int a = 0;

static int s = 0;

a создается и инициализируется при каждом вызове функции

s создается при старте программы

s удаляется при завершении программы

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

Слайд 12

Классы памяти переменных Функции в Си Пример. Автоматическая и статическая переменные

Классы памяти переменных

Функции в Си

Пример. Автоматическая и статическая переменные

auto = 0,

static = 0
auto = 0, static = 1
auto = 0, static = 2
auto = 0, static = 3
auto = 0, static = 4
Слайд 13

Классы памяти переменных Классы памяти переменных Регистровый класс памяти (register) задается

Классы памяти переменных

Классы памяти переменных

Регистровый класс памяти (register)
задается ключевым словом register

при описании переменной перед указанием типа
register int k=0;
при возможности регистровые переменные размещаются в регистрах процессора, а не в памяти
регистровые переменные не имеют адреса, т.е. к ним не применим оператор &
в остальном аналогичны автоматическим переменным
чаще всего регистровый класс памяти используется для переменных-счетчиков цикла

void main() {
register int i; /* регистровая переменная */
for (i=0; i<15; ++i) printf(“%d\n”, i);
}

Слайд 14

Классы памяти переменных Классы памяти переменных Внешний класс памяти (extern) внешние

Классы памяти переменных

Классы памяти переменных

Внешний класс памяти (extern)
внешние переменные – переменные,

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

Определение

Использование

Использование

Использование

Слайд 15

Классы памяти переменных Классы памяти переменных Внешний класс памяти (extern) определение

Классы памяти переменных

Классы памяти переменных

Внешний класс памяти (extern)
определение внешней переменной должно

быть единственным на программу (только в одном файле)
int global=100;
при определении внешней переменной не требуется указывать специальных ключевых слов!
для использования внешних переменных, определенных за пределами данного файла, нужно поместить объявление внешней переменной
extern int global;

Определение

Слайд 16

Классы памяти переменных Классы памяти переменных Внешний класс памяти (extern) определение

Классы памяти переменных

Классы памяти переменных

Внешний класс памяти (extern)
определение внешней переменной –

в одном файле
в остальных – объявление переменной

Определение

Объявление

Объявление

Слайд 17

Классы памяти переменных Классы памяти переменных Внешний класс памяти (extern) инициализировать

Классы памяти переменных

Классы памяти переменных

Внешний класс памяти (extern)
инициализировать внешние переменные можно

только в определении (не в объявлении)
int global=1024; /* корректно */
extern int global=0; /* некорректно */
инициализировать внешние переменные можно только константными выражениями без вызовов функций
int global=(8*1024)/2; /* корректно */
float wrong=2*sqrt(global); /* некорректно */
Слайд 18

Классы памяти переменных Классы памяти переменных Внешний статический класс памяти Внешние

Классы памяти переменных

Классы памяти переменных

Внешний статический класс памяти
Внешние переменные могут быть

объявлены как статические
Область видимости внешней статической переменной – файл, в котором она определена (а не вся программа)

Внешняя статическая переменная

Доступна в том же файле ниже определения

Недоступна в других файлах

Слайд 19

Классы памяти переменных Квалификаторы const и volatile Определение любой переменной может

Классы памяти переменных

Квалификаторы const и volatile

Определение любой переменной может предваряться квалификаторами

const или volatile
Квалификатор const запрещает любые изменения значения переменной после ее инициализации
const double PI = 3.141592;
const int N = 1000;
Квалификатор volatile извещает компилятор о том, что значение переменной может изменяться внешними по отношению к программе процессами
volatile unsigned Time;
учитывается при оптимизации кода программы
Слайд 20

Классы памяти переменных Описание переменных: общая схема Квалификаторы и модификаторы const

Классы памяти переменных

Описание переменных: общая схема

Квалификаторы и модификаторы

const

volatile

auto

static

register

extern

signed

unsigned

short

long

long long

int

char

float

double

Класс памяти

Изменя- емость

Знаковость

Длина

Тип

Примеры:
static volatile

unsigned long long int TimeTicks;
register const unsigned long double MyRealVar;
auto signed short int x_coord;
Слайд 21

Препроцессор Препроцессор: что это? Директивы препроцессора Подключение файлов Условная компиляция Макросы

Препроцессор

Препроцессор: что это?
Директивы препроцессора
Подключение файлов
Условная компиляция
Макросы

Слайд 22

Препроцессор Препроцессор: что это? Препроцессор – специальная программа, автоматически вызываемая компилятором

Препроцессор

Препроцессор: что это?

Препроцессор – специальная программа, автоматически вызываемая компилятором перед собственно

компиляцией
1й проход: вызов препроцессора для Си-файла
2й проход: вызов компилятора для измененного Си-файла

Препроцессор

Компилятор

Слайд 23

Препроцессор Директивы препроцессора Три основных типа директив Подключение файла #include Условной

Препроцессор

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

Три основных типа директив
Подключение файла
#include
Условной компиляции
#if, #ifdef, #ifndef, #else, #elif,

#endif
Макро-подстановка (макрос)
#define, #undef
Правила построения директив
Всегда начинается с #
Может появляться в любом месте программы
В той же строке может содержаться комментарий
Воспринимается как одна строка, если явно не продолжена
#define MAX_CHARS 300 /*Макс. длина имени файла*/
#define MAX_FILES \ 100
Слайд 24

Препроцессор Подключение файлов Зачем? Позволяет разделять программу или модули на интерфейс

Препроцессор

Подключение файлов

Зачем?
Позволяет разделять программу или модули на интерфейс и реализацию (см.

Принципы структурного программирования)
Интерфейс (заголовочный файл) содержит все объявления модуля (константы, переменные, типы данных, функции)
Рекомендуемое расширение заголовочного файла: .h
Имена заголовочных файлов пользователя – в “ … ”
#include “mydefs.h”
Имена системных заголовочных файлов – в < … >
#include
Слайд 25

Препроцессор Условная компиляция Зачем? Один и тот же исходный код для

Препроцессор

Условная компиляция

Зачем?
Один и тот же исходный код для различных платформ
Необходимость иметь

различный код для специфических ситуаций
Условная компиляция
#ifdef name
#ifndef name
#if expr
#elif expr
#else
#endif
Удаление макро- определений
#undef PLUSONE
Слайд 26

Препроцессор Условная компиляция Другой пример

Препроцессор

Условная компиляция

Другой пример

Слайд 27

Препроцессор Макросы Предоставляют возможность параметризованной автоматической текстовой замены Зачем? Порождаемый код

Препроцессор

Макросы

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

контроля типов
Макро-определение
#define MAXLINE 120
#define lower(c) ((c)-`A’+‘a’)
Макро-подстановка
char buf[MAXLINE+1]; превращается в char buf[120+1];
c = lower(buf[i]); превращается в c = ((buf[i])-`A’+‘a’);
Слайд 28

Препроцессор Макросы: используйте ( ) Всегда заключайте параметры макро-функций в скобки!!!

Препроцессор

Макросы: используйте ( )

Всегда заключайте параметры макро-функций в скобки!!!

#define plusone(x) x+1

i

= 3*plusone(2);

… i = 3*2+1;

#define plusone(x) ((x)+1)

i = 3*plusone(2);

… i = 3*((2)+1);

Слайд 29

Препроцессор Макросы: думайте о побочных эффектах Частой причиной побочных эффектов являются

Препроцессор

Макросы: думайте о побочных эффектах

Частой причиной побочных эффектов являются операции “++“

и “--“
Всегда избегайте дополнительных трюков с параметрами макро-функций

#define max(a, b) ((a)>(b)?(a):(b))
...
y = max(i++, j++);
...

...
y = ((i++)>(j++)?(i++):(j++));
...

Слайд 30

Препроцессор Макросы: оператор # Оператор # в макросах конвертирует аргумент в

Препроцессор

Макросы: оператор #

Оператор # в макросах конвертирует аргумент в строковую константу
Всегда

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

#define PRINT_INT(x) printf( #x “= %d\n”, x)
...
PRINT_INT( x * y );
...

...
printf( “x * y” “= %d\n”, x*y);
...

Слайд 31

Препроцессор Макросы: оператор ## Нужен крайне редко Склеивает две лексемы #define

Препроцессор

Макросы: оператор ##

Нужен крайне редко
Склеивает две лексемы

#define GENERIC_MAX(type) \
type type##_max(type x,

type y) \
{ return x > y ? x : y };
...
GENERIC_MAX(float) ...

...
float float_max(float x, float y)
{ return x > y ? x : y };
...

Слайд 32

Препроцессор Другие директивы: #error Позволяет препроцессору инициировать ошибки компиляции #error сообщение

Препроцессор

Другие директивы: #error

Позволяет препроцессору инициировать ошибки компиляции
#error сообщение
Пример

#if defined(WINDOWS)
...
#elif defined(LINUX)
...
#elif

defined(MAC_OS_X)
...
#else
#error no OS specified
#endif
Слайд 33

Препроцессор Другие директивы: #line Позволяет переопределить номер строки для компилятора #line

Препроцессор

Другие директивы: #line

Позволяет переопределить номер строки для компилятора
#line n
или
#line n “file”
Пример
>

gcc one.c
> two.c: In function 'main':
> two.c:101: 'i' undeclared (first use in this function)
Слайд 34

Препроцессор Макросы: некоторые общие свойства Макросы могут содержать макросы Препроцессор может

Препроцессор

Макросы: некоторые общие свойства

Макросы могут содержать макросы
Препроцессор может делать несколько проходов

для повторной замены
Макро-определение имеет силу до конца файла
Макрос не может определяться дважды
Перед повторным определением необходимо аннулировать предыдущее с помощью #undef
Слайд 35

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

Препроцессор

Препроцессор: резюме

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

файлов
Условная компиляция
Макросы
Макросы иногда полезны, но требуют повышенного внимания (опасны!)
Убедитесь, что Вы помните основные правила
Используйте скобки, где только можно
Думайте о побочных эффектах