Добавил:
КТ Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
var21 / Лабораторная работа №7(БДЗ).docx
Скачиваний:
2
Добавлен:
04.10.2024
Размер:
93.84 Кб
Скачать

Универсальный (обобщенный) указатель void

Существует проблема приведения типов при работе с указателями.

int *ip;

double *dp;

dp = ip; // будет предупреждение или ошибка транслятора

Предупреждение выдается не зря - подобные операции с указателями, если это сделано по ошибке, приводят к трудно выявляемым ошибкам.

В подобных случаях необходимо явное приведение типов указателей:

dp = (double*) ip;

Переменных типа void не существует.

  • Первое применение void - отсутствие значения, указание того, что функция ничего не возвращает или не содержит параметров.

  • Второе применение void – указатели на неопределённый тип данных, они могут хранить значения указателей различных типов. У таких указателей отсутствует информация о размерах и внутренней структуре адресуемого участка памяти.

Свойства указателя void

Действия с указателем void требуют явного приведения типов

  1. присваивание: 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* и инкремент адреса

Выделение памяти из кучи.

  1. Функция 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) );

  1. Функция 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;

}

  1. Функция realloc() позволяет изменять размер выделенного участка динамической памяти

После создания динамического массива вы можете увеличить или уменьшить его размер.

realloc () имеет два параметра :

  • указатель на уже имеющуюся область динамической памяти

  • новый размер этой области.

Возвращаемое значение - указатель на захваченную область нужного размера в байтах.