Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Понятие указателя. Статические и динамические переменные. Функции для работы с динамической памятью. Примеры.




Ответ:

Виды указателей

Переменная-указатель предназначен для хранения адреса памяти

В языке Си различают три вида указателей:

· Указатель на объект.

· Указатель на void.

· Указатель на функцию.

Указатель не является самостоятельным типом, он всегда связан с каким-либо другим конкретным типов.

Понятие указателя

Переменная в программе – это объект, который имеет:

· Имя, которое соответствует адресу того участка памяти, который ей выделен.

· Тип, который соответствует размеру выделенного участка памяти.

· Значение, которое соответствует содержимому этого участка памяти.

· Имя и тип переменной (ее адрес и размер) не может изменяться, а значение – может изменяться.

Указатель – это переменная, которая содержит адрес другой переменной:

Независимо от того, на переменную какого типа (и размера) указывает указатель, размер переменной-указателя всегда постоянный и зависит от используемой модели памяти (как правило – 4 байта).

Причины использования указателей:

· Возможность просто передать адрес участка памяти (переменной) вместо копирования содержимого этого участка памяти (возможно очень большого размера)

· Возможность работы в разных местах программы с одним и тем же фрагментом данных, а не с его отдельными копиями

Объявление указателя

Синтаксис описания переменной-указателя:

тип * имя;

Где:

тип – тип переменной, на которую может указывать указатель;

имя – идентификатор переменной типа указатель, т.е. обычное имя переменной

Рекомендуется при объявлении переменной- указателя использовать префикс или суффикс ptr – это улучшит "читабельность" программы.

int *t;

double *ptr_d;

char *count_Ptr;

int **ptr_P;

К переменным-указателям на объекты можно применять следующие базовые операции (операторы):

· Присваивание (инициализация)

· Разыменование

· Взятие адреса переменной-указателя (адрес адреса)

· Сложение указателя с целочисленным значением

· Инкремент, декремент указателя

· Вычитание из указателя целочисленного значения

· Вычисление разности двух указателей

· Сравнение двух указателей (только для указателей на объекты одинакового типа)

Статические и динамические переменные

Адрес поименованной ячейки памяти также может определяться как на этапе компиляции, так и во время выполнения программы. По времени создания переменные бывают статическими и динамическими.

Первые создаются в момент запуска программы или подпрограммы, а вторые создаются в процессе выполнения программы.

Динамическая адресация нужна только тогда, когда количество поступающих на хранение данных заранее точно не известно. Такие данные размещают в специальных динамических структурах, тип которой выбирается в соответствии со спецификой задачи и с возможностями выбранной системы программирования. Это может быть стек, куча, очередь и т. п.

Для работы с динамической памятью в языке С используются следующие функции: malloc, calloc, free, realloc.
Рассмотрим их подробнее.

void *malloc(size_t size);

В качестве входного параметра функция принимает размер памяти, которую требуется выделить. Возвращаемым значением является указатель на выделенный в куче участок памяти.
Для выделения памяти под 1 000 000 int`ов необходимо выполнить следующий код:

int * p = malloc(1000000*sizeof(int));
Если ОС не смогла выделить память (например, памяти не хватило), то malloc возвращает 0.
После окончания работы с выделенной динамически памятью нужно освободить ее. Для этой цели используется функция free, которая возвращает память под управление ОС.

void free(void *ptr);

В качестве входного параметра в free нужно передать указатель, значение которого полученно из функции malloc. Вызов free на указателях полученных не из malloc (например, free(p+10)) приведет к неопределенному поведению. Это связанно с тем, что при выделении памяти при помощи malloc в ячейки перед той, на которую указывает возвращаемый функцией указатель операционная система записывает служебную информацию (см. рис.). При вызове free(p+10) информация находящаяся перед ячейкой (p+10) будет трактоваться как служебная.

void *calloc(size_t nmemb, size_t size);

Функция работает аналогично malloc, но отличается синтаксисом (вместо размера выделяемой памяти нужно задать количество элементов и размер одного элемента) и тем, что выделенная память будет обнулена. Например, после выполнения

int * q = (int *) calloc(1000000, sizeof(int))
q будет указывать на начало массива из миллиона int`ов инициализированных нулями.

void *realloc(void *ptr, size_t size);

Функция изменяет размер выделенной памяти (на которую указывает ptr, полученный из вызова malloc, calloc или realloc). Если размер указанный в параметре size больше, чем тот, который был выделен под указатель ptr, то проверяется, есть ли возможность выделить недостающие ячейки памяти подряд с уже выделенными. Если места недостаточно, то выделяется новый участок памяти размером size и данные по указателю ptr копируются в начало нового участка.










Последнее изменение этой страницы: 2018-04-12; просмотров: 464.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...