Распределение памяти - Лекция: Общее знакомство

^ Распределение памяти Функция malloc( )
Пусть нам нужно распределить память для запоминания используемых данных. Некоторые ячейки памяти распределяются автоматически, Например, мы можем объявить

char str[ ] = "Символьная строка";

Будет выделена память, достаточная для запоминания этой строки. Мы можем запросить определенный объем памяти:

int mas[150];

Это описание выделяет 150 ячеек памяти, каждая из которых предназначена для запоминания целого значения. Но язык Си позволяет нам распределять дополнительную память во время работы программы. Предположим, мы пишем программу и не знаем, сколько данных нам придется вводить. Тогда можно выделить нужный нам, по нашему предположению, объем памяти, а затем, если понадобится, потребовать еще. Чтобы сделать это, нужно использовать функцию malloc( ). И без указателей тут не обойтись!

/* добавляем память, если необходимо */

#include

#define STOP " " /* сигнал прекращения ввода */

#define BLOCK 100 /*байты памяти */

#define LIM 40 /*предельная длина вводимой строки*/

#define MAX 50 /*максимальное число вводимых строк */

#define TIME 20000 /* большая задержка времени */

main ( )

{

char store[BLOCK]; /* исходный блок памяти*/

char symph[LIM]; /* приемник вводимых строк*/

char *end; /* указывает на конец памяти */

char *starts[MAX]; /* указывает на начала строк*/

int index = 0; /*количество вводимых строк */

int count; /* счетчик*/

сhar malloc( ); / * распределитель памяти */

start[o]=store;

end=starts[0]+BLOCK-1;

puts("Введите строки по одной");

puts("в начале нажимайте клавишу[ввод ]");

puts("Начинайте!.");

while(strcmp(fgets(symph,LIM,stdin),STOP) != 0

&& index
if(strlen(symph)>end - starts[index]) {

/* действия при недостатке памяти для

запоминания вводимых данных*/

puts("подождите, программа попробует найти

дополнительную память");

starts[index]=malloc(BLOCK);

end=starts[index]+BLOCK- 1;

for(count=0; count
puts("память найдена");

}

strcpy(starts[index],symph);

starts[index+1]=starts[index] + strlen(symph)+1;

if(++index
printf("Строка: %d. продолжайте.\n", index);

}

puts("Вывод программы");

for(count=0; count
puts(starts[count]);

}

Давайте посмотрим, что делает функция malloc( ). Она берет аргумент в виде целого без знака, которое представляет количество требуемых байтов памяти. Так, malloc(BLOCK) требует 100 байт. Функция возвращает указатель на тип char в начало нового блока памяти. Мы использовали описание

char *malloc( );

чтобы предупредить компилятор, что malloc( ) возвращает указатель на тип char. Поэтому мы присвоили значение этого указателя элементу массива starts[index] при помощи оператора

starts[index]=malloc(BLOCK);

Предположим, что мы хотим работать с памятью типа int, а не char. Mожете и здесь использовать malloc( ). Вот как это делается:

char malloc( );

/* по-прежнему описываем как указатель на char */

int *newmem; newmem = (int)malloc(100);

/* используем операцию приведения типа */

Снова требуется 100 байт. Операция приведения типа преобразует значение, возвращенное указателем на тип char, в указатель на тип int. Если в системе int. занимает два байта памяти, это значит, что 100 байт можно использовать для запоминания 50 целых чисел.
^ Функция calloc( )
Другую возможность распределения памяти дает нам применение функции calloc( ).

char *calloc( ); long *newmem;

newmem=(long *) calloc(100,sizeof(long));

Функция calloc( ) возвращает указатель на char. Нужно использовать оператор приведения типа, если вы хотите запомнить другой тип. calloc( ) имеет два аргумента, и оба они должны быть целыми без знака. Первый аргумент содержит количество требуемых ячеек памяти. Второй аргумент - размер каждой ячейки в байтах. Функция calloc( ) обнуляет содержимое всего блока. Ваша библиотека языка Си возможно представляет несколько других функций управления памятью, вы можете исследовать их самостоятельно!

16. Лекция: Функции в примерах
^ Функция получения случайных чисел
Сейчас мы покажем генератор псевдослучайных чисел. Это означает, что фактическая последовательность чисел предсказуема, но они разбросаны довольно равномерно в пределах возможного диапазона значений.

Схема начинает с числа, называемого "зерно". Она использует его для создания нового числа, которое становится новым зерном. Затем новое зерно можно использовать для создания более нового зерна и т.д. Чтобы эта схема работала, функция случайных чисел должна помнить зерно, которое она использовала при последнем вызове. Отметим, здесь нужно использовать статическую переменную!

/* Первая версия функции rand( )*/

rand( )

{

static int randx = 1;

randx = (randx * 25173 + 13849)%65536;

/* магическая формула */

return(randx);

}

Статическая переменная randx начинает со значения 1 и изменяется при помощи магической формулы каждый раз при вызове функции. Результатом в нашей системе является число, находящееся в диапазоне -32768 до 32767. Системы с разной длиной переменной типа int будут давать различные результаты.

Проверим работу функции при помощи этого простого драйвера:

/*драйвер 1 функции rand( ) */

main( )

{

int count;

for(count = 1; count <= 5; count++)

printf(" %d\n",rand( ));

}

Получим результат:

-26514

-4449

20196

-20531

3882

Эта последовательность чисел выглядит довольно случайной. Запустим драйвер еще раз. Теперь имеем

-26514

-4449

20196

-20531

3882

Получилось абсолютно то же самое. Это и есть псевдоэффект. Каждый раз, когда работает основная программа, мы начинаем с одного и того же значения зерна, равного 1. Можно обойти эту проблему, введя вторую функцию srand( ), которая позволяет вновь устанавливать зерно в начальное значение. Хитрость заключается в том, чтобы сделать randx внешней статической переменной, известной только функциям rand( ) и srand( ). Эти две функции нужно хранить в своем собственном файле и компилировать этот файл отдельно. Вот модификатор программы:

/* Файл для rand( ) и srand( ) */

static int randx = 1;

rand( )

{

randx = (randx * 25173 + 13849) % 65536;

return(randx);

}

srand(x)

unsigned x;

{

randx = x;

}

Используем другой драйвер:

/* драйвер 2 функции rand( ) */

main( )

{

int count;

int seed;

printf(" Введите свое значение зерна.\n");

scanf("%d", & seed);

srand(seed);

/* установите зерно в начальное значение */

for(count = 1; count <= 5; count++)

printf("%\n",rand( ));

}

Программа проработала один раз:

Введите свое значение зерна.


1

-26514

-4449

20196

-20531

3882

Используя значение 1 для переменной seed, получаем те же значения, что и прежде. Введем значение 2 и посмотрим, что получится:

2

23832

20241

-1858

-30417

-16204

Мы получили другую последовательность чисел.

4091021207432162.html
4091183412641230.html
4091343939250900.html
4091485642665369.html
4091749364409741.html