Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Указательные выражения. Адресная арифметика.
Указательные выражения К указателям можно применить операцию присваивания. Указатели одного и того же типа могут использоваться в операции присваивания, как и любые другие переменные.Пример: { int x = 10; int *p, *g; // объявление указателя p = &x; // установка указателя p на переменную x g = p; // указатель g тоже указывает на x printf("p = %d", p); // вывод на экран содержимого p (вывод адреса) printf("\n g = %d", g); // вывод адреса printf("\n x = %d", x, "*g = %d", *g); /* вывод на экран величины x и величины, находящейся по адресу указателя g */ } В языке С допустимо прмсвоить указателю любой адрес памяти. Однако, если объявлен указатель на целое число (int *p;), а по адресу, которому присвоен данному указателю, находится переменная x типа float, то при компиляции программы будет выдано сообщение об ошибке в строке p = &x. Эту ошибку можно исправить, преобразовав указатель на int к типу указателя на float явным преобразованием типа: p = (int*)&x;но при этом теряется информация о том, на какой тип указывал исходный указатель. Адресная арифметика Над указателями можно выполнять унарные операции: инкремент и декремент. При выполнении операций ++ и -- значение указателя увеличивается или уменьшается на длину типа, на который ссылается используемый указатель. Пример: int *ptr, a[10]; ptr=&a[5]; ptr++; // равно адресу элемента a[6] ptr--; // равно адресу элемента a[5]В бинарных операциях сложения и вычитания могут участвовать указатель и величина типа int. При этом результатом операции будет указатель на исходный тип, а его значение будет на указанное число элементов больше или меньше исходного. Пример: int *ptr1, *ptr2, a[10]; int i=2; ptr1=a+(i+4); // равно адресу элемента a[6] ptr2=ptr1-i; // равно адресу элемента a[4] В операции вычитания могут участвовать два указателя на один и тот же тип. Результат такой операции имеет тип int и равен числу элементов исходного типа между уменьшаемым и вычитаемым, причем если первый адрес младше, то результат имеет отрицательное значение. Пример: int *ptr1, *ptr2, a[10]; int i; ptr1=a+4; ptr2=a+9; i=ptr1-ptr2; // равно 5 i=ptr2-ptr1; // равно -5 Значения двух указателей на одинаковые типы можно сравнивать в операциях ==,!=, <, <=, >, >= при этом значения указателей рассматриваются просто как целые числа, а результат сравнения равен 0 (ложь) или 1 (истина). Пример: int *ptr1, *ptr2, a[10]; ptr1=a+5; ptr2=a+7; if (prt1>ptr2) a[3]=4; В данном примере значение ptr1 меньше значения ptr2 и поэтому оператор a[3]=4 не будет выполнен.
Связь массивов и указателей В языке Си имя массива трактуется как указатель-константа на массив. Пусть в программе объявлен массив: int X[10]; В таком случае Х является указателем на нулевой элемент массива в памяти компьютера. В связи с этим является истинным отношение X==&X[0] Следовательно, для доступа к элементам массива кроме индексированных имен можно использовать разадресованные указатели по принципу:
Имя[индекс] тождественно *(имя+индекс) Например, для описанного выше массива Х взаимозаменяемы следующие обозначения элементов: X[5], или *(Х+5), или *(5+Х). В языке Си операция [ играет роль знака операции сложения адреса массива с индексом элемента.
25. Функции динамического распределения памяти. Calloc Функция Выделяет оперативную память. Синтаксис #include <stdlib.h void * calloc(size_t nitems, size_t size); Файл, содержащий stdlib.h,alloc. прототип Описание calloc обеспечвает доступ к динамической области памяти. Динамическая область памяти доступна для динамического распределения блоков памяти переменной длины. Многие структуры данных, например, деревья и списки, используют распределение динамической области памяти. calloc выделяет блок памяти размером nitems x size. Блок обнуляется. Если вы хотите выделить блок, размер которого превышает 64К то нужно использовать функцию farcalloc. Возвращаемое calloc возвращает указатель на выделенный блок. значение calloc возвращает NULL, если недостаочно памяти для выделения нового блока, или nitems или size равны 0. Переносимость Поддерживается в системах UNIX и определена в ANSI C. Описана в Керниган и Риччи. Смотрите также faralloc, free, malloc, realloc.Пример: #include<stdio.h> #include<alloc.h> #include<string.h> int main(void) { char *str = NULL; /* выделить память для строки */ str = calloc(10,sizeof(char)); if(str) { /* скопировать в строку "Hello" */ strcopy(str,"Hello"); /* вывести строку */ printf("Строка: %s\n",str); /* освободить память */ free(str); } else printf("Недостаточно памяти\n"); } return(0); } Malloc Функция.Выделяет память. Синтаксис #include<stdlib.h> #include<alloc.h> void *malloc(size_t size); Файл, содержащий stdlib.h и alloc.h прототип Описание Функция обеспечивают выделение блока памяти, размером size байт. Она позволяет программе выделять память по необходимости и столько, сколько нужно. Динамическая область памяти доступна для динамического размещения блоков памяти переменной длины. Многие структуры данных, такие как "деревья" или "списки" – естественным образом используют динамическое распределение памяти. В малых моделях памяти, вся область памяти между концом сегмента данных и вершиной программного стека доступна для использования, за исключением 256-байтовой границы, находящейся непосредственно перед вершиной стека. Данная граница предназначена для наращивания стека прикладной программы (плюс небольшое количество, требуемое для DOS). В больших моделях памяти все пространство после программного стека до конца физической памяти доступно для динамической области. Возвращаемое Функция malloc возвращает указатель на блок выде значени ленной памяти. Если для размещения блока недостаточно памяти, функция malloc возвращает NULL. Содержимое блока остается неизменным. Если аргумент size равен 0, то функция возвращает NULL. Переносимость Функция доступна в системах UNIX и поддерживается стандартом ANSI C. Смотрите также allocmem, calloc, coreleft, farcalloc, farmalloc, free, realloc. Версия, которая будет написана здесь, не имеет ограничений: вызовы malloc и free могут выполняться в любом порядке: malloc делает запрос в операционную систему на выделение памяти тогда, когда она требуется. Эти программы иллюстрируют приемы, позволяющие получать машинно-зависимый код сравнительно машинно-независимым способом, и, кроме того, они могут служить примером применения таких средств языка, как структуры, объединения и typedef.
Никакого ранее скомпилированного массива фиксированного размера, из которого выделяются куски памяти, не будет. Функция malloc запрашивает память у операционной системы по мере надобности. Поскольку и другие действия программы могут вызывать запросы памяти, которые удовлетворяются независимо от этого распределителя памяти, пространство, которым заведует malloc, необязательно представляет собой связный кусок памяти. Поэтому свободная память хранится в виде списка блоков. Каждый блок содержит размер, указатель на следующий блок и само пространство. Блоки в списке хранятся в порядке возрастания адресов памяти, при этом последний блок (с самым большим адресом) указывает на первый. При возникновении запроса на память просматривается список свободных блоков, пока не обнаружится достаточно большой блок. Такой алгоритм называется "поиском первого подходящего" в отличие от алгоритма "поиска наилучшего подходящего", который ищет наименьший блок из числа удовлетворяющих запросу. Если размер блока в точности соответствует требованиям, то такой блок исключается из списка и отдается в пользование. Если размер блока больше, чем требуется, от него отрезается нужная часть - она отдается пользователю, а ненужная оставляется в списке свободных блоков. Если блока достаточного размера не оказалось, то у операционной системы запрашивается еще один большой кусок памяти, который присоединяется к списку свободных блоков. Процедура освобождения сопряжена с прохождением по списку свободных блоков, поскольку нужно найти подходящее место для освобождаемого блока. Если подлежащий освобождению блок примыкает с какой-то стороны к одному из свободных блоков, то он объединяется с ним в один блок большего размера, чтобы по возможности уменьшить раздробленность (фрагментацию) памяти. Выполнение проверки, примыкают ли блоки друг к другу, не составляет труда, поскольку список свободных блоков всегда упорядочен по возрастанию адресов.
Существует проблема, состоящая в том, что память, выдаваемая функцией malloc, должна быть соответствующим образом выровнена с учетом объектов, которые будут в ней храниться. Хотя машины и отличаются друг от друга, но для каждой из них существует тип, предъявляющий самые большие требования на выравнивание, и, если по некоему адресу допускается размещение объекта этого типа, то по нему можно разместить и объекты всех других типов. На некоторых машинах таким самым "требовательным" типом является double, на других это может быть int или long.
Свободный блок содержит указатель на следующий блок в списке, свой размер и собственно свободное пространство. Указатель и размер представляют собой управляющую информацию и образуют так называемый "заголовок". Чтобы упростить выравнивание, все блоки создаются кратными размеру заголовка, а заголовок соответствующим образом выравнивается. Этого можно достичь, сконструировав дддобъединение, которое будет содержать соответствующую заголовку структуру и самый требовательный в отношении выравнивания тип. Для конкретности выберем тип long.
|
|||||||
Последнее изменение этой страницы: 2021-08-16; просмотров: 41; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.139.97.157 (0.014 с.) |