12.1. Основные понятия

При определении статического массива: <тип> <имя_массива> [количество_элементов] , имя_массива становится указателем на область памяти, выделяемой для размещения элементов массива. Количество элементов должно быть константой. Таким образом, размеры памяти, выделяемой под массив, заданы в определении массива. Но иногда нужно, чтобы размеры памяти были не фиксированными, а выделялись в ходе выполнения программы при решении конкретной задачи.

Формирование массивов с переменными размерами можно организовать с помощью указателей и средств для динамического выделения памяти. Эти средства описаны в файле <alloc.h>. Функции malloc() и calloc() динамически выделяют память в соответствии со значениями их параметров и возвращают адрес начала выделенного участка памяти. Тип возвращаемого значения указателя void *. Его можно преобразовать к указателю любого типа с помощью явного приведения типа. Функция free(void *) освобождает память, выделенную с помощью malloc() или calloc().

int *p;

p=(int *)malloc(size); //Указателю на целое p присваивается адрес начала выделенной области памяти размером size байт.

p=(int *)calloc(n, size); //Указателю на целое p присваивается адрес начала выделенной области памяти размером n*size байт.

free(p); //Освобождает выделенную по адресу p память. Преобразование указателя любого типа к типу void * осуществляется автоматически, так что в качестве фактического параметра можно подставить указатель любого типа без явного приведения типов.


12.2. Одномерные динамические массивы

Пример формирования одномерного динамического массива

#include <stdio.h>

#include <conio.h>

#include <alloc.h>

main()

{float *p,d;

 int i,n;

 printf("\n input n:");

 scanf("%d",&n);

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

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

  { printf("x[%d]=",i);

    scanf("%f",&d);

    p[i]=d;

 }

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

  {  if (i%4==0) printf("\n");

     printf("\t x[%d]=%6.2f",i,p[i]);

   }

 free(p);

 getch();

}

Доступ к участкам выделенной памяти выполняется с помощью операции индексирования: p[i].


12.3. Двумерные динамические массивы

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

  1. Определяем указатель на массив указателей , задающий адреса начала строк матрицы: тип **uk.
  2. Вводим размеры матрицы n,m.
  3. Создаём динамический массив указателей на указатели начала строк : uk=(тип **)malloc(n*sizeof(тип *));
  4. В цикле выделяем память под n массивов – строк по m элементов в каждом: for (i=0;i<n;i++) uk[i]=(тип *)malloc(m*sizeof(тип));
  5. Обработка массива (работа с индексированными элементами uk[i][j]).
  6. В цикле освобождаем память, занятую под n массивов – строк : for (i=0;i<n;i++) free(uk[i]);
  7. Освобождаем память, занятую под массив указателей : free(uk).

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

Составить программу, создающую динамическую матрицу размером n*n, заполнить матрицу случайными числами. Вычислить сумму каждой строки и поместить суммы строк в одномерный динамический массив.

#include <stdio.h>

#include <conio.h>

#include <stdlib.h>

#include <alloc.h>

void main()

{ int n,j,i;

  float ** matr; float * mass; // Объявляем matr - указатель на массив указателей //mass – указатель на одномерный массив

  clrscr();

  printf("Введите размер квадратной матрицы n: "); scanf("%d",&n);

  mass=(float *)malloc(n*sizeof(float )); // Выделяем память под массив mass

  if (mass==NULL)

   {puts("не создан динамический массив!");

    return;}

  matr=(float **)malloc(sizeof(float *)*n); // Выделяем память под массив указателей

  if (matr==NULL)

    {puts("не создан динамический массив!");

     return;}

  randomize();

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

    { matr[i]=(float *)malloc(sizeof(float)*n); // Выделяем память под i-ю строку

      if (matr[i]==NULL)

        {puts("не создан динамический массив!");

         return;}

      for (j=0;j<n;j++) matr[i][j]=random(100);

    }

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

   { mass[i]=0;

     for (j=0;j<n;j++)

        mass[i]+=matr[i][j];
  
   }

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

   { for (j=0;j<n;j++)

       printf("\t%6.2f",matr[i][j]);

    printf("\n");

   }

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

     printf("\n сумма %d строки %8.2f",i,mass[i]);

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

      free(matr[i]); //Освобождаем память i – й строки

  free(matr); // Освобождаем память массива указателей

  free(mass); // Освобождаем память массива сумм

  getch();

}

 

12.4. Контрольные вопросы

1. Отличия динамического массива от статического.

2. Как создать одномерный динамический массив?

3. Как создать динамическую матрицу?

4. Как освобождается память, занятая под динамические структуры?