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

Обновлено: 21.11.2024

Я хотел бы знать, в чем разница между статическим и динамическим выделением памяти?

Не могли бы вы объяснить это на каком-нибудь примере?

7 ответов 7

Это стандартный вопрос для собеседования:

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

Выделяется ли память во время выполнения с помощью calloc() , malloc() и им подобных. Иногда ее также называют памятью кучи, хотя она не имеет ничего общего с ссылкой на структуру данных кучи.

Куча памяти сохраняется до тех пор, пока не будет вызвана функция free(). Другими словами, вы управляете временем жизни переменной.

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

Это так называемая "стековая" память, которая выделяется, когда вы входите в новую область (обычно когда новая функция помещается в стек вызовов). Как только вы выйдете за пределы области действия, значения автоматических адресов памяти станут неопределенными, и доступ к ним будет ошибкой.

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

Выделение статической памяти

Выделяется во время компиляции * , а время жизни переменной в статической памяти равно времени жизни программы.

В C статическая память может быть выделена с помощью ключевого слова static. Областью действия является только единица компиляции.

Все становится интереснее, когда рассматривается ключевое слово extern. Когда внешняя переменная определена, компилятор выделяет для нее память. Когда внешняя переменная объявлена, компилятор требует, чтобы эта переменная была определена в другом месте. Если не объявить/не определить переменные extern, это вызовет проблемы с компоновкой, а неспособность объявить/определить статические переменные вызовет проблемы компиляции.

в области файла ключевое слово static является необязательным (вне функции):

Но не в области действия функции (внутри функции):

Технически extern и static — это два разных класса переменных в C.

* Примечания по выделению статической памяти

Говорить, что статическая память выделяется во время компиляции, несколько сбивает с толку, особенно если учесть, что компьютер компиляции и хост-компьютер могут быть разными или даже могут иметь разную архитектуру.

Возможно, лучше думать, что выделение статической памяти обрабатывается компилятором, а не выделяется во время компиляции.

Например, компилятор может создать большой раздел данных в скомпилированном двоичном файле, и когда программа загружается в память, адрес внутри сегмента данных программы будет использоваться в качестве местоположения выделенной памяти. Это имеет заметный недостаток, заключающийся в том, что скомпилированный двоичный файл становится очень большим, если используется много статической памяти. Можно написать многогигабайтный двоичный файл, сгенерированный менее чем из полдюжины строк кода. Другой вариант заключается в том, что компилятор вводит код инициализации, который будет выделять память другим способом, прежде чем программа будет выполнена. Этот код зависит от целевой платформы и ОС. На практике современные компиляторы используют эвристику, чтобы решить, какой из этих вариантов использовать. Вы можете попробовать это сами, написав небольшую программу на C, которая выделяет большой статический массив элементов размером 10k, 1m, 10m, 100m, 1G или 10G. Для многих компиляторов размер двоичного файла будет продолжать расти линейно с размером массива, и после определенного момента он снова уменьшится, поскольку компилятор использует другую стратегию распределения.

Регистрация памяти

Последний класс памяти — это регистровые переменные. Как и ожидалось, регистровые переменные должны размещаться в регистре процессора, но фактически решение остается за компилятором. Вы не можете превратить регистровую переменную в ссылку, используя адрес-оф.

Большинство современных компиляторов умнее вас выбирают, какие переменные следует помещать в регистры :)

Язык C поддерживает два вида выделения памяти через переменные в программах на C:

  • Статическое размещение — это то, что происходит, когда вы объявляете статическую или глобальную переменную. Каждая статическая или глобальная переменная определяет один блок пространства фиксированного размера. Пространство выделяется один раз при запуске вашей программы (часть операции exec) и никогда не освобождается.
  • Автоматическое выделение происходит при объявлении автоматической переменной, такой как аргумент функции или локальная переменная. Пространство для автоматической переменной выделяется при вводе составного оператора, содержащего объявление, и освобождается при выходе из этого составного оператора.

В GNU C размер автоматического хранилища может меняться. В других реализациях C это должно быть константой.

Третий важный вид выделения памяти, динамическое выделение, не поддерживается переменными C, но доступен через функции библиотеки C GNU.

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

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

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

Или вам может понадобиться блок для каждой записи или каждого определения во входных данных; поскольку вы не можете знать заранее, сколько их будет, вы должны выделять новый блок для каждой записи или определения по мере чтения.

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

Динамическое размещение не поддерживается переменными C; не существует класса хранения «динамический», и никогда не может быть переменной C, значение которой хранится в динамически выделенном пространстве. Единственный способ получить динамически выделенную память — через системный вызов (обычно через вызов функции библиотеки GNU C), а единственный способ обратиться к динамически выделенному пространству — через указатель. Поскольку это менее удобно, а фактический процесс динамического размещения требует больше времени для вычислений, программисты обычно используют динамическое размещение только тогда, когда ни статическое, ни автоматическое размещение не годятся.

Например, если вы хотите динамически выделить некоторое пространство для хранения структуры foobar , вы не можете объявить переменную типа struct foobar, содержимое которой является динамически выделенным пространством. Но вы можете объявить переменную типа указателя struct foobar * и присвоить ей адрес пробела. Затем вы можете использовать операторы ‘ * ’ и ‘ -> ’ для этой переменной-указателя, чтобы обратиться к содержимому пробела:

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

Фон

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

Для программы выделяется два типа памяти:

Память стека выделяется во время выполнения во время компиляции. Это называется выделением статической памяти.

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

Выделение статической памяти

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

Основные особенности:

  • Переменные выделяются постоянно
  • Распределение выполняется до выполнения программы
  • Он использует структуру данных, называемую стеком, для реализации статического размещения.
  • Менее эффективно
  • Повторное использование памяти не предусмотрено.

Пример

  • Все переменные в приведенной ниже программе размещены статически.
  • В этом типе распределения вы строго выделяете память для своих данных во время компиляции. Это также называется простым выделением памяти. Он в основном используется и очень прост в применении.

Удаление выделенной памяти

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

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

Как следует из названия, значение статических переменных сохраняется до конца программы. Переменная может быть объявлена ​​static с помощью ключевого слова static like

Статическая переменная может быть внутреннего или внешнего типа в зависимости от места объявления.

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

.

Пример

Вывод

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

Преимущества выделения статической памяти

  • Простота использования.
  • Эффективное время выполнения.
  • Не нужно беспокоиться о выделении/перераспределении/освобождении памяти
  • Переменные остаются постоянно выделенными.

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

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

Шрея Гупта

Ведущий специалист по разработке программного обеспечения в студенческом клубе разработчиков Thapar | Стажер в OpenGenus | B. Технология гражданского строительства в Инженерно-технологическом институте Тапара

Улучшено и проверено:

Фонд OpenGenus

цикл for в C++

Цикл For состоит из трех компонентов: оператора инициализации, тестового выражения и оператора обновления. Мы исследовали цикл for в C++, представили примеры и сравнили его с циклом while.

Харшита Сахаи

оператор goto в C

Операция goto — это инструкция перехода, которую иногда также называют оператором безусловного перехода. Оператор goto может использоваться для перехода из любого места в любое в пределах функции. Использование оператора goto крайне не рекомендуется, и его можно избежать с помощью операторов break и continue.

Харшита Сахаи

Выделение памяти, как правило, означает, что компьютерные программы и службы выполняются для частичного или полного резервирования пространства или виртуальной памяти компьютера. Этот процесс известен как выделение памяти. Этот процесс представляет собой аппаратную операцию и достигается за счет управления памятью через операционные системы и программные приложения. В общем, есть статическое и динамическое выделение памяти, тогда как в языке программирования C мы увидим динамическое выделение памяти, когда программы выделяются в памяти во время выполнения, а статическое выделение памяти — это процесс выделения памяти при написании программы C, которая означает, что память выделяется во время компиляции.

Как работает выделение памяти в C?

В языке C статическое и динамическое выделение памяти также известно как память стека и память кучи, которые выделяются во время компиляции и во время выполнения соответственно.

Веб-разработка, языки программирования, тестирование программного обеспечения и другое

1. Выделение статической памяти

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

Давайте рассмотрим пример ниже:

Код:

недействительное воспроизведение
int x;
>
int main()
int y;
инт с[10];
возврат 1;
>

Объяснение: В приведенной выше программе переменные x, y и care распределены статически, поэтому память строго выделяется во время компиляции для переменных данных. Обратите внимание, что удаление памяти необходимо, когда переменные не используются, потому что это приведет к утечке памяти. Поэтому при статическом распределении памяти он автоматически освобождает память в зависимости от области действия переменной, что означает, что память освобождается, как только управление переменной заканчивается.

Обучение программированию на C (3 курса, 5 проектов) 3 онлайн-курса | 5 практических проектов | 34+ часа | Поддающийся проверке сертификат об окончании | Пожизненный доступ
4,5 (8 563 оценки)

<р>2. Переменная может быть внутренне или внешне объявлена ​​как статическая, в которой ее значение сохраняется до конца программы, где это можно сделать с помощью ключевого слова static перед объявлением переменной. Внутри или вне функции могут быть объявлены внутренние или внешние статические переменные.

Давайте рассмотрим пример:

Вывод:

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

1. malloc()

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

Синтаксис:

Код:

mptr = (int*) malloc(100 * sizeof (int));

В приведенном выше примере оператор выделяет 200 байтов памяти, поскольку размер int в C равен 2 байтам, а указатель переменной mptr содержит адрес первого байта в памяти.

2. calloc()

Это также называется непрерывным размещением. Как и в malloc(), не инициализируется какой-либо бит памяти. Но в calloc() он выделяет память вместе с обнулением битов.

Синтаксис:

(CastType*) calloc(n, size)

Код:

cptr = (int*) calloc(35, sizeof (int));

В этой функции приведенный выше пример оператора выделяет непрерывное пространство памяти примерно для 35 элементов типа данных «int».

3. бесплатно()

Как обсуждалось выше, пространство памяти должно быть освобождено или освобождено, если оно не используется. При динамическом выделении памяти функции malloc() и calloc() только выделяют память, но не могут освободить память сами по себе, поэтому это делается с помощью метода free() явным образом для освобождения неиспользуемой памяти во избежание утечки памяти.

Синтаксис:

Код:

Вывод:

4. релок()

Как следует из названия, при динамическом выделении памяти, если пользователь хочет выделить больше памяти, что означает больше памяти, чем указано или требуется программе, мы можем использовать эту функцию realloc() для изменения размера выделенной памяти. ранее.

Синтаксис:

переменная_указателя, n);

Код:

Предположим, если мы хотим изменить размер памяти с 200 байт на 600 байт. Давайте посмотрим, как это можно сделать с помощью realloc().

char *rptr;
rptr = malloc(200);
rptr = realloc(rptr, 600);

Заключение

Распределение памяти в языке программирования C выполняется просто с помощью статического выделения памяти, которое выделяет память во время компиляции или, можно сказать, перед выполнением программы, а также имеет другой тип, известный как динамическое выделение памяти, которое выделяет память во время выполнения или выделяет память во время выполнения. выполнение программы, в которой используются 4 различные функции, такие как malloc(), calloc(), free() и realloc(). Оба метода имеют разные плюсы и минусы.

Рекомендуемые статьи

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

Читайте также: