Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 5 статей:

Методические подходы к анализу финансового состояния предприятия

Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века

Ценовые и неценовые факторы

Характеристика шлифовальных кругов и ее маркировка

Служебные части речи. Предлог. Союз. Частицы

КАТЕГОРИИ:






Динамическое распределение памяти из кучи (heap).




Часто бывает удобно создать новый объект, который существует до тех пор, пока он не станет ненужным. В частности, бывает удобно создать объект, который можно использовать после возврата из функции, где он был создан. (определение из лекции)

Или Динамическое распределение памяти — способ выделения оперативной памяти компьютера для объектов в программе, при котором выделение памяти под объект осуществляется во время выполнения программы.

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

Преимущества динам. распределения:

· Гибкость использования

· Часто бывает удобно создать новый объект, который существует до тех пор, пока он не станет ненужным

· Бывает удобно создать объект, который можно использовать после возврата из функции, где он был создан.

Недостатки:

· Большие накладные расходы

· Сложность использования

13. Отличие глобальных, статических и локальных переменных. С примерами. Область жизни и область видимости. Локальные переменные: Переменная, объявленная внутри функции, считается локальной, т.е. на неё можно ссылать только внутри данной функции. При любом присвоении вне функции, используется другая переменная, которая не имеет ничего общего, кроме имени, к переменной объявленной внутри функции. При выходе из функции, в которой объявлена локальная переменная, эта переменная уничтожается вместе со значением.

 

1) static int a=0 2) int a=0
#include <stdio.h> #include <stdlib.h>   int f(){ static int a=0; a=a+1; printf("%i \n",a); }   int main() { f(); f(); system("pause"); return 0; } #include <stdio.h> #include <stdlib.h>   int f(){ int a=0; a=a+1; printf("%i \n",a); }   int main() { f(); f(); system("pause"); return 0; }

 

В первом примере, переменная статическая – память под неё выделяется сразу при загрузке программы и инициализируется нулем, а потом при каждом вызове функции f выделение памяти уже не происходит, поэтому изменяется старое значение статической переменной a. Во втором примере, при каждом заходе в функцию, для автоматической переменной a выделяется память и инициализируется нулем, поэтому пи каждом вызове функции f, мы видим, что она выводит “1”.

Глобальные переменные: Глобальные переменные, в отличие от локальных, доступны в любой точке программы. Но чтобы изменить значение глобальной переменной, необходимо специально объявить её как глобальную. Глобальные переменные хранятся в отдельной фиксированной области памяти, созданной компилятором специально для этого. Глобальные переменные используются в тех случаях, когда разные функции программы используют одни и те же данные. Однако рекомендуется избегать излишнего использования глобальных переменных, потому что они занимают память в течение всего времени выполнения программы, а не только тогда, когда они необходимы. Кроме того, и это еще более важно, использование глобальной переменной делает функцию менее универсальной, потому что в этом случае функция использует нечто, определенное вне ее. К тому же большое количество глобальных переменных легко приводит к ошибкам в программе из-за нежелательных побочных эффектов. При увеличении размера программы серьезной проблемой становится случайное изменение значения переменной где-то в другой части программы, а когда глобальных переменных много, предотвратить это очень трудно. В следующем примере переменная count объявлена вне каких бы то ни было функций. Ее объявление расположено перед main(), однако, оно может находиться в любом месте перед первым использованием этой переменной, но только не внутри функции. Объявлять глобальные переменные рекомендуется в верхней части программы.

#include <stdio.h>

int count; /* глобальная переменная count */

void func1(void);

void func2(void);

int main(void)

{

count = 100;

func1();

return 0;

}

void func1(void)

{

int temp;

temp = count;

func2();

printf("count равно %d", count); /* напечатает 100 */

}

void func2(void)

{

int count;

for(count=1; count<10; count++)

putchar('.');

}

Статические переменные: В отличие от переменных, объявленных параметрами и уничтожающимися при выходе из функции, статическая переменная сохраняет своё значение и при повторном вызове. Время жизни и область видимости объектов Время жизни – это части программы или вся программа, при выполнении которой переменная существует. Область видимости – это часть программы или вся программа, когда возможно получить доступ к объекту. В общем случае область видимости и время жизни не совпадают.

  Время жизни Область видимости
Глобальные переменные От момента запуска до момента окончания программы – на протяжении выполнения всей программы. Видимость вся программа, кроме блоков, когда переменная перекрывается локальной переменной с тем же именем.
Статические переменные внутри функций От момента запуска до момента окончания программы – на протяжении выполнения всей программы. Видна только внутри функции. Может быть перекрыта одноименными переменными во внутренних блоках {}, например, внутри цикла.
Локальные переменные - автоматические Существуют от момента объявления до окончания того блока, в котором переменная объявлена. Блок – это все, что заключено между {}. Функция – то же блок. Видны внутри блока, в котом объявлены. Могут быть перекрыты одноименными переменными во внутренних блоках.

 

Стек
↓ ↑
Динамически распределяемая область памяти
Глобальные переменные
Код программы

14. Автоматический стековый механизм распределения памяти. Используется ли стековый механизм для глобальных переменных? Стек – это область памяти, в которой хранятся локальные переменные и параметры функций. При вызове функции ее параметры и локальные переменные помещаются в стек. Стек функционирует по принципу стакана – значение, помещенное в стек первым, оказывается на дне стека, в то время как последнее значение – на вершине стека. По завершении работы функции все данные, принадлежащие этой функции, удаляются из стека. Очистка стека начинается с вершины, т. е. со значений, помещенных в стек последними;Скомпилированная программа С имеет четыре логически обособленные области памяти.Первая — это область памяти, содержащая выполнимый код программы. Во второй области хранятся глобальные переменные. Оставшиеся две области — это стек и динамически распределяемая область памяти. Стек используется для хранения вспомогательных переменных во время выполнения программы. Здесь находятся адреса возврата функций, аргументы функций, локальные переменные и т.п. Глобальные переменные хранятся отдельно!!!

 

15. Стековый механизм распределения памяти. Примеры и траектория вызова функций. Стек – это область памяти, в которой хранятся локальные переменные и параметры функций. При вызове функции ее параметры и локальные переменные помещаются в стек. Стек функционирует по принципу стакана – значение, помещенное в стек первым, оказывается на дне стека, в то время как последнее значение – на вершине стека. По завершении работы функции все данные, принадлежащие этой функции, удаляются из стека. Очистка стека начинается с вершины, т. е. со значений, помещенных в стек последними;

16. Отличие статических переменных от локальных. Статические переменные внутри функций: Время жизни от момента запуска до момента окончания программы-на протяжении выполнения всей программы. Область видимости: видна только внутри функции. Может быть перекрыта одноименными переменными во внутренних блоках {}, например, внутри цикла. Статические переменные объявляются директивой static. Они инициализируются только один раз - при первом вызове функции и сохраняют свое значение даже после выхода из функции. В следующий раз при новом вызове функции статические переменные будут иметь то же значение, которое они имели перед выходом из функции в послений раз.Статические переменные объявляются в пределах описания функции и поэтому доступны для использования только в пределах той функции, в которой они объявлены. Пример объявления статической переменной:int GetOpenPositionsNumber(){static int Count = 0;...}Локальные переменные – автоматические: Время жизни существуют от момента объявления до окончания того блока, в котором переменная объявлена. Блок – это все, что заключено между {}. Функция – тоже блок. Область видимости: видны внутри блока, в котором объявлены. Могут быть перекрыты одноименными переменами во внутренних блоках. Их значения и даже сам факт, что локальные переменные существуют, известны только данной функции, Другими словами, если вы объявляете локальную переменную с именем salary в функции payroll, то другие функции не имеют доступа к значению переменной salary. Фактически, другие функции не имеют никакого представления о том, что переменная salary существует. При объявлении локальных переменных внутри функции очень вероятно, что имя локальной переменной, объявляемой вами в одной функции, будет таким же, как и имя переменной, используемой в другой функции. Как уже упоминалось, локальные переменные известны только в текущей функции. Таким образом, если две функции используют одно и то же имя для своих локальных переменных, это не приводит к конфликту. Время жизни – это части программы или вся программа, при выполнении которой переменная существует. Область видимости – это часть программы или вся программа, когда возможно получить доступ к объекту.

17. Функции для работы с динамической памятью. Примеры. Динамическое распределение памяти из кучи (heap). Часто бывает удобно создать новый объект, который существует до тех пор, пока он не станет ненужным. В частности, бывает удобно создать объект, который можно использовать после возврата из функции, где он был создан. (определение из лекции) Или Динамическое распределение памяти — способ выделения оперативной памяти компьютера для объектов в программе, при котором выделение памяти под объект осуществляется во время выполнения программы. (используется, если на момент написания программы известен только тип данных, не известен объем выделяемой памяти. В этом случае память должна выделяться в момент исполнения программы). Часто бывает удобно создать новый объект, который существует до тех пор, пока он не станет ненужным. В частности, бывает удобно создать объект, который можно использовать после возврата из функции, где он был создан. Для работой с памятью используются следующие основные функции:

  Выделение памяти Высвобождение памяти
C Функция:malloc, calloc Прототип функции malloc(): void *malloc(size_t кол-во_байт);t кол-во_байт – тип, описанный в <stdlib.h>, как unsigned int. Функция:free прототип: void free(void * p) р — указатель на участок памяти, выделенный перед этим функцией malloc
C++ Функция:New Функция:delete

Основу системы динамического распределения в С составляют функции malloc() и free(). Функция malloc() выделяет память, а free() — освобождает ее. Это значит, что при каждом запросе функция malloc() выделяет требуемый участок свободной памяти, a free() освобождает его, то есть возвращает системе.

Функции malloc и free описаны в библиотеке <stdlib.h>.

Функция malloc() возвращает указатель типа void *, поэтому его можно присвоить указателю любого типа.

int *p1 = malloc(400);

double *p2= malloc(400);

Выделаются НЕПРЕРЫВНО 400 байт.

Указатели p1 и p2 указывают на начало блока.

По-сути – p1 ссылается на массив из 100 элементов типа int, а p2 – ссылается на 50 элементов типа double.

При успешном выполнении malloc() возвращает указатель на первый байт непрерывного участка памяти, выделенного в динамически распределяемой области памяти.

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

int *p;p = malloc(50*sizeof(int));

Если в динамически распределяемой области памяти недостаточно свободной памяти для выполнения запроса, то память не выделяется и malloc() возвращает нуль (0 или NULL). При каждом размещении данных необходимо проверять, состоялось ли оно.

p = malloc(100);if(!p) { printf("Нехватка памяти.\n"); exit(1); Не использовать указатель р, если он равен нулю! Функция free() противоположна функции malloc() в том смысле, что она возвращает системе участок памяти, выделенный ранее с помощью функции malloc(). Иными словами, она освобождает участок памяти, который может быть вновь использован функцией malloc().

18. Что такое sizeof. Почему надо использовать sizeof при написании программ. С помощью операции sizeof можно определить размер памяти которая соответствует идентификатору или типу. Операция sizeof имеет следующий формат: sizeof(выражение). В качестве выражения может быть использован любой идентификатор, либо имя типа, заключенное в скобки. Отметим, что не может быть использовано имя типа void, а идентификатор не может относится к полю битов или быть именем функции. Если в качестве выражения указанно имя массива, то результатом является размер всего массива (т.е. произведение числа элементов на длину типа), а не размер указателя, соответствующего идентификатору массива. Однако убедиться, что вы каждый раз выделяете и освобождаете один и тот же объем памяти, недостаточно. Вы должны обеспечить распределение правильного объема памяти. Надежнее всего использовать в программе функцию SizeOf. Это не только обеспечивает, что вы выделяете и освобождаете один и тот же объем, но гарантирует, что при изменении размера типа ваша программа все равно будет выделять нужную память.






Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных