Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабник по C.pdf
Скачиваний:
74
Добавлен:
01.06.2015
Размер:
876.9 Кб
Скачать

– 28 –

#ifdef M

...

#else

...

#endif

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

#undef M отменяет последнюю по порядку директиву определения M.

8. ДИНАМИЧЕСКОЕ РАСПРЕДЕЛЕНИЕ ПАМЯТИ, СПИСКИ

8.1.ВЫДЕЛЕНИЕ И ОСВОБОЖДЕНИЕ ДИНАМИЧЕСКОЙ ПАМЯТИ

Для выделения динамической памяти в С используются функции malloc и calloc.

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

char *ptr;

ptr = malloc( 100 );

Согласно этому оператору во время выполнения программы будет выделено 100 байтов памяти. Аргумент функции malloc – целое выражение.

char str[10], *ptr;

ptr = malloc( sizeof( str )); // выделяется 10 байтов

Тип возвращаемого функцией значения – указатель на char, т.е. *char. Поэтому при формировании памяти с другим типом указателя целесообразно использовать операцию приведения типа:

float mas[10], *ptr1; struct rec week, *ptr2;

ptr1 = (float*)malloc( sizeof( mas ));

ptr2 = (struct rec*)malloc( sizeof( week ));

Функция calloc имеет два аргумента: 1-ый – количество выделяемых полей, 2-ой – размер поля;

long *ptr;

ptr = (long*)calloc( 100, sizeof( long ));// Выделяется 100 4-х байтовых полей

Функция calloc очищает выделяемые поля.

Память, выделенная функциями malloc и calloc, возвращается в пул свободной памяти функцией free( указатель ).

Функции работы с динамической памятью описаны в файле alloc.h.

8.2. СПИСКИ

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

Элемент списка обычно определяется в виде структуры, составляющими которой являются информационная часть и адресная часть. В последней содержатся ссылки (адреса) на смежные элементы.

Рассмотрим программу формирования однонаправленного линейного списка путем включения нового элемента в его начало. Список имеет следующую структуру.

© 1998 Калачев Д.П., Лутай В.Н.

– 29 –

Head I1 A2 I2 A3 ... In NULL

Рис.1. Структура однонаправленного линейного списка

На рис. 1 Head – указатель на начало списка (адрес первого элемента), Ii – информационные части элементов, Ai – указатели на i-e элементы, NULL – пустой адрес, обозначающий конец списка.

Для каждого нового элемента необходимо:

выделить память;

заполнить информационную часть;

занести в его адресную часть адрес предыдущего элемента;

зафиксировать его адрес как адрес начала списка.

Вприведенной ниже программе формируется список из 5 элементов; информационная часть – один символ.

#include <stdio.h> #include <alloc.h>

//Описание одного элемента списка struct elem{

char Inf;

struct elem* adr; };

void main(){

struct elem *head, // указатель на начало *t;

struct elem *insert(struct *elem, char);

//Функция вставки; первый аргумент-значение адресной части элемента, 2-й- информационной

void print(struct elem*); // Функция вывода списка на экран char ch;

int i, j, k;

head=NULL; // Начальное значение указателя на начало списка for (i=0; i<5; i++) {

ch=getchar(); // Ввод информационной части if( t=insert(head, ch)) head=t;

else break;

}

print(head); } //main

struct elem *insert( struct elem *head, char symb) {

struct elem *buf, sp; // дополнительный указатель и структура

if((buf = (struct elem*)malloc(sizeof sp))==NULL) // Выделение памяти под новый элемент

return( NULL ):

//возвращает NULL, если недостаточно памяти

buf->Inf = symb;

// Занесение информационной части

buf->adr= head;

// Занесение адреса предыдущего элемента

return( buf );

// Фиксация адреса нового элемента как указателя на начало

} //insert

 

void print (struct elem *head) { // Функция выводит элементы, начиная с первого while(head!=NULL) {

putchar(head->inf); head=head->adr;

}

} //print

© 1998 Калачев Д.П., Лутай В.Н.