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

4. Динамическое распределение памяти

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

Рассмотрим пример такой программы.

#include <stdio.h>

main( )

{

int *x,*w,y,z;

64

y=-15;

*x=16;

w=&y;

printf("\n Размер указателя x составляет %d байт",

sizeof(x));

printf("\n Значение указателя x равно %u байт", x);

printf("\n Значение по этому адресу равно %d",*x);

printf("\n Адрес переменной y равен %u", &y);

printf("\n Адрес переменной z равен %u", &z);

printf("\n Значение *w равно %d", *w);

}

Ошибка, содержащаяся в программе, одна из наиболее распространенных.

По отдельности каждая строка программы правильна. Проблема заключается в неинициализированном указателе x. Объявление int *x приведёт к тому, что под

переменную x выделется блок оперативной памяти. В нашем случае не выделен

участок оперативной памяти для размещения числа 16. Получается, что 16 будет записано в неизвестную область памяти: поскольку переменная х неини-циализирована, то в ней хранится неизвестное число, и запись *x=16 приводит

к тому, что по неизвестному адресу расположится число 16. Это может привес-ти к следующему: 1) стирание части кода операционной системы, 2) стирание части кода драйвера или другой программы, 3) стирание кода самой выполня-емой программы. Компилятор такую ошибку распознать не сможет.

Исправить ситуацию можно, если использовать функцию динамического

распределения памяти malloc( ), прототип которой хранится в головном файле

alloc.h. Функция malloc( ) выделит в оперативной памяти два байта, в которых

можно разместить целое число 16, и адрес этих двух байтов гарантированно не

совпадает ни с одним из адресов, используемых операционной системой.

Таким образом, в исходную программу необходимо добавить две строки:

  1. директиву препроцессора #include <alloc.h>

  2. непосредственно перед оператором *x=16; строку x=(int*) malloc(sizeof(int));.

#include <stdio.h>

#include <alloc.h>

main( )

{

int *x,*w,y,z;

y=-15;

x=(int*) malloc(sizeof(int));

*x=16;

w=&y;

printf("\nРазмер указ. x составляет %d байт",sizeof(x));

printf("\n Значение указателя x равно %u байт", x);

printf("\n Значение по этому адресу равно %d",*x);

printf("\n Адрес переменной y равен %u", &y);

printf("\n Адрес переменной z равен %u", &z);

printf("\n Значение *w равно %d", *w);

}

Описание функции malloc(). Функция malloc() динамически распределяет

блок памями размером size байт. Возвращаемое значение — указатель на

выделенную область памяти.

#include <alloc.h>

void *malloc(size);

unsigned size;

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

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

Пример 1. Рассмотрим работу с массивом без динамического

распределения оперативной памяти.

main ()

{

float b[100];

int n,i;

printf(" Введите размер массива \n, n<=100");

scanf ("%u", &n);

for(i=0; i<=n-1; i++)

{

/* иницииализация массива */

printf (" Введите элемент массива b[%u]", i+1);

scanf("%f", b+i);

}

. . .

}

Недостаток программы заключается в том, что мы резервируем больше

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

расходуется неэкономно.

Пример 2. Работа с массивами с использованием динамического

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

#include <stdio.h>

#include <alloc.h>

main()

{

float *b;

int n;

printf ("\n Задайте размер массива \n , n= ")

scanf("%u",&n);

b=(float*)malloc(n*sizeof(float));

for(i=0;i<=n-1;i++)

{

printf("Введите элемент массива b[%u]", i+1);

scanf("%f", &b[i]);

}

. . .

В программе объявляется указатель с именем b, который содержит адрес пере-менной типа float. Оператор программы вводит размер массива n. С помощью функции malloc( ) выделяется память под массив из n чисел типа float и иници-ализируется указатель. Память компьютера при этом расходуется экономно.

Графическое представление выделения памяти под массив дано на рис.3.

Рис.3.

6. Динамическое размещение двухмерных массивов.

Допустим нам необходимо разместить в оперативной памяти матрицу, которая содержит вещественные числа. Размерность матрицы n*m, где n — количество строк; m —количество столбцов. Для размещения матрицы необходимо зарезервировать с помощью функции malloc() блок памяти размером sizeof (float)*n*m байт.

Для работы с матрицей определим следующее правило для передвижения по

блоку оперативной памяти:

*(b+i*n+j),

где i — номер строки (0<=i<n); j — номер столбца (0<=j<m). Таким образом и

будет осуществлятся доступ к элементу массива с индексами i и j.

Графическое представление размещения двухмерного массивав

оперативной памяти представлено на рис. 4.

Рис. 4.

Программа

#include <stdio.h>

#include <alloc.h>

main()

{

float *b;

int n, m, i, j;

printf ("\n Введите количество строк: n= ");

scanf ("%u", &n);

printf("\n Введите количество столбцов: m= ");

scanf ("%u", &m);

b=(float*)malloc(sizeof(float)*m*n);

for (i=0,i<=n-1, i++)

for (j=0; j<=m-1, i++)

{

printf ("\n введите элемент %u

строки, %u столбца ", i+1, j+1);

scanf ("%f", b+i*n+j);

}

for (i=0, i<=n-1, i++)

for (j=0, j<=m-1, j++)

{

. . .

* (b+i*n+j)= . . .

/*обработка массива*/

. . .

}

. .