- •Определение структуры включает
- •2 Этапа:
- •Оператор typedef
- •Определение структуры безымянного типа
- •Оператор sizeof
- •Доступ к элементам структуры.
- •Структуры и функции.
- •Динамическая работа с памятью.
- •Распределение памяти компьютера.
- •Универсальный (обобщенный) указатель void
- •Свойства указателя void
- •Выделение памяти из кучи.
- •Особенности realloc().
- •Освобождение динамической памяти.
- •Правила работы с динамической памятью.
- •Варианты заданий. Общие требования
Универсальный (обобщенный) указатель void
Существует проблема приведения типов при работе с указателями.
int *ip;
double *dp;
dp = ip; // будет предупреждение или ошибка транслятора
Предупреждение выдается не зря - подобные операции с указателями, если это сделано по ошибке, приводят к трудно выявляемым ошибкам.
В подобных случаях необходимо явное приведение типов указателей:
dp = (double*) ip;
Переменных типа void не существует.
Первое применение void - отсутствие значения, указание того, что функция ничего не возвращает или не содержит параметров.
Второе применение void – указатели на неопределённый тип данных, они могут хранить значения указателей различных типов. У таких указателей отсутствует информация о размерах и внутренней структуре адресуемого участка памяти.
Свойства указателя void
Действия с указателем void требуют явного приведения типов
присваивание: void *vp;
char *cp;
double *dp;
vp = cp;
vp = dp;
cp = (char*)vp;
dp = (double*)vp;
Действия с адресами указателей void * запрещены (отсутствует понятие размера элемента). Но можно использовать явное преобразование типа указателя.
void *ptr;
int V[10];
ptr = V;
s=s+(*ptr) ; // ошибка!!!
s = s + *(int*)ptr ; // преобразование к типу int* и обращение к данным
Действие «разовое» для следующего действие потребуется новое преобразование :
(int*)ptr++; // преобразование к типу int* и инкремент адреса
Выделение памяти из кучи.
Функция malloc() память не инициализирует. В аргументе указывается размер памяти в байтах.
Пример: создать динамический массив из ста символов, заполнить его нулями:
#include <stdlib.h>
main()
{ int i;
char *p;
/*Резервируем 100 байтов под массив char */
p = (char*) malloc (100);
for (i=0; i<100; i++)
*p++ = 0;
return 0;
}
Для массива любого другого типа, например, int, придется вычислять размер памяти в байтах, для этой цели очень удобен оператор sizeof().
int *p;
/*Резервируем место под 100 элементов int*/
p = (int*) malloc( 100 * sizeof(int) );
То же самое действие, но так лучше! sizeof использует тип указателя – невозможно ошибиться
p = (int*) malloc( 100 * sizeof(*p) );
Функция calloc(), не только захватывает память, но и очищает ее (заполняет байты нулями), у нее два аргумента:
количество элементов;
размер элемента в байтах.
void main()
{ char *сp;
int *ip;
/*Резервируем и очищаем 100 элементов char*/
сp = (char* ) сalloc(100, 1 );
/*Резервируем и очищаем 100 элементов int */
ip = (int*) сalloc(100, sizeof(*ip) );
}
Функции calloc (nelm, elmsize) и malloc(nelm*elmsize) выделят одно и то же количество байт памяти, но calloc также и очистит её.
В примерах выше мы пользовались динамической памятью для создания массивов, но таким же образом можно выделять память и под структуры, переменные встроенных типов и т.п.
На самом деле все эти функции работают с "абстрактной" памятью, и им абсолютно безразлично, как программист ее будет использовать. А тот указатель (точнее тип указателя), в который вы записываете адрес области, лишь помогает программе интерпретировать эту область нужным вам образом.
Поставьте вместо указателя на int указатель на структуру - и вы будете работать с динамически созданной структурой или массивом структур:
void main()
{ COMP *ptr;
ptr = (COMP*)malloc(sizeof(COMP)) ;
ptr->re = 1.0;
ptr->im = 0.0;
}
Функция realloc() позволяет изменять размер выделенного участка динамической памяти
После создания динамического массива вы можете увеличить или уменьшить его размер.
realloc () имеет два параметра :
указатель на уже имеющуюся область динамической памяти
новый размер этой области.
Возвращаемое значение - указатель на захваченную область нужного размера в байтах.
