Здавалка
Главная | Обратная связь

Cтатическое и динамическое выделение памяти



Статическая память – это область хранения всех глобальных и статических переменных. Переменные статической памяти объявляются лишь единожды и уничтожаются по завершении программы.

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

Предыдущая Оглавление Следующая  
Предыдущая Оглавление Следующая
           

Указатели

Указатель - это переменная, содержащая адрес другой переменной.Указатели очень широко используются в языке C. Это происходит отчасти потому, что иногда они дают единственную возможность выразить нужное действие, а отчасти потому, что они обычно ведут к более компактным и эффективным программам, чем те, которые могут быть получены другими способами.

Так как указатель содержит адрес объекта, это дает возможность "косвенного" доступа к этому объекту через указатель. Предположим, что х - переменная, например, типа int, а рх - указатель, созданный неким еще не оговоренным способом. Унарная операция & (операция взятия адреса) выдает адрес объекта, так что оператор

pxх = &x;

присваивает адрес x переменной px; говорят, что px "указывает" на x.

Операция & применима только к переменным и элементам массива, конструкции вида:

&(х-1) и &3

являются незаконными.

Унарная операция * (операция разыменования) рассматривает свой операнд как адрес конечной цели и обращается по этому адресу, чтобы извлечь содержимое. Следовательно, если y тоже имеет тип int, то

y = *px;

присваивает y содержимое того, на что указывает px. Так последовательность

px = &x; y = *px;

присваивает y то же самое значение, что и оператор

y = x;

Переменные, участвующие во всем этом необходимо объявить, а для этого необходимо выяснить, каков же синтаксис создания указателя:

тип_данных * имя_указателя;

Прокомментируем:

Тип_данных - любой существующий в программе тип. Должен СТРОГО!!! совпадать с типом той переменной, чей адрес будет храниться в указателе. Это связано с тем, что в момент разыменования операционной системе необходимо знать не только адрес объекта, но и его точный тип данных для правильности использования пространства по этому адресу. Отклонение от этого правила приведёт ошибке на этапе компиляции.

Примечание: Кстати! Размер, занимаемый указателем в оперативной памяти не зависит от его типа. Размер указателя определяется разрядностью операционной системы и тем, сколько байт требуется для хранения адреса. Например, в 32-разрядной системе это будет 4 байта, в 64-разрядной - 8 байт.

Из этого выводим объявление, использованных выше переменных:

int x, y; int *px;

C описанием для x и y мы уже неодонократно встречались. Описание указателя

int *px;

является новым и должно рассматриваться как мнемоническое; оно говорит, что комбинация *px имеет тип int. Это означает, что если px появляется в контексте *px, то это эквивалентно переменной типа int. Фактически синтаксис описания переменной имитирует синтаксис выражений, в которых эта переменная может появляться. Это замечание полезно во всех случаях, связанных со сложными описаниями. Например,

double A, *dp;

говорит, что A и *dp имеют в выражениях значения типа double.

Указатели могут входить в выражения. Например, если px указывает на целое x, то *px может появляться в любом контексте, где может встретиться x. Например:

y = *px + 1; //присваивает y значение, на 1 большее значения x;   cout<< *px;//выводит текущее значение x;   d = sqrt((double) *px)//получает в d квадратный корень из x, причем до передачи функции sqrt значение x преобразуется к типу double.

В выражениях вида

y = *px + 1;

унарные операции * и & связаны со своим операндом более крепко, чем арифметические операции, так что такое выражение берет то значение, на которое указывает рх, прибавляет 1 и присваивает результат переменной y.

Разыменование указателя может располагаться и в левой части присваиваний. Если px указывает на x, то

*px = 0;

полагает х равным нулю, а

*px += 1;

увеличивает его на единицу, как и выражение (правда здесь изменения самой переменной x не происходит)

(*px) + 1;

Круглые скобки в последнем примере необходимы; если их опустить, то поскольку унарные операции, подобные * и ++, выполняются справа налево, это выражение увеличит px, а не ту переменную, на которую он указывает.

И наконец, так как указатели являются переменными, то с ними можно обращаться, как и с остальными переменными. Если py - другой указатель на переменную типа int, то

py = px;

копирует содержимое рх в py, в результате чего py указывает на то же, что и px. Напоминаем, что для данной процедуры указатели должны совпадать по типу данных!!!

Итак, мы познакомились с основами теории указателей. Следующий раздел урока расскажет вам о том, какая связь прослеживается между нашей сегодняшней темой и массивами.

Предыдущая Оглавление Следующая  
Предыдущая Оглавление Следующая
           






©2015 arhivinfo.ru Все права принадлежат авторам размещенных материалов.