Почему не нужно освобождать статические массивы?
Мне интересно, почему статические массивы не нужно освобождать? Я знаю, что при создании динамического массива, например.
int *p;
p = malloc(10*sizeof(int));
мы должны освободить выделенную память, используя:
free(p);
И для статического массива в функции статический массив будет автоматически освобожден, когда вызываемая функция будет выполнена.
Я не понимаю, что при возврате статического массива с помощью такой функции:
int *subFunc(){
static int a[5] = {1,2,3,4,5};
return a;
}
int main(){
int *p;
p = subFunc();
}
Если статический массив автоматически освобождается после завершения выполнения, то как мы можем получить доступ к значениям статического массива правильно?
Ответы
Ответ 1
Если статический массив автоматически освобождается после завершения выполнения, то как мы можем получить доступ к значениям статического массива правильно?
Нет, это не так. static
переменные инициализируются перед запуском main()
, а его время жизни - это полное выполнение программы. Таким образом, они могут быть return
из функций (в которых они определены) и могут быть доступны. Они не являются локальными (для функций), выходящими за время жизни, когда функция завершает выполнение.
Связанный, цитирующий из C11
, глава §6.2.4
Объект, идентификатор которого объявлен без спецификатора класса хранения _Thread_local
, либо с внешней или внутренней связью, либо с классом хранения спецификатор static
, имеет статическую продолжительность хранения. Его срок службы - это полное выполнение программа, и ее сохраненное значение инициализируется только один раз, до запуска программы.
Что касается области действия переменной static
внутри функции, да, она ограничена самой функцией, как указано в главе §6.2.1,
[...] Если спецификатор декларатора или типа, который объявляет, что идентификатор появляется внутри блока или в списке объявлений параметров в определение функции, идентификатор имеет область действия блока, которая заканчивается в конце связанный блок. [...]
Это означает, что вы не можете использовать массив a
вне subFunc()
, так как a
не отображается вне subFunc()
.
Однако, когда вы return
массив (возвращающий массив вызывает распад указателя на первый элемент массива, FWIW), поскольку время жизни массива static
- это полное выполнение программы, доступ к возвращенному указателю (конечно, в пределах границ) является вполне допустимым и законным.
Ответ 2
Статические переменные продолжают существовать даже после блока, в котором они определены. Таким образом, значение статической переменной в функция сохраняется между повторными вызовами функций к тому же функция. Объем статических автоматических переменных идентичен автоматических переменных, то есть локально к блоку, в котором он находится определены; однако выделенное хранилище становится постоянным для продолжительность программы. Статические переменные могут быть инициализированы в их декларации; однако инициализаторы должны быть постоянными выражениями, и инициализация выполняется только один раз во время компиляции, когда память выделено для статической переменной. - источник
Статический массив или переменные не будут освобождены, когда управление выходит из этой функции. Область статической переменной локальна для функции, в которой она объявлена, но ее время жизни находится во всей программе.
Ответ 3
И для статического массива в подфункции статический массив будет автоматически освобожден, когда вызванная подфункция будет выполнена.
Это неверно. Статические массивы не создаются при вводе функции, и они не уничтожаются, когда вы ее оставляете.
Статическая переменная и данные внутри нее действительно много похожи на глобальную переменную! Единственное, что локально для функции - это имя. (Вы услышите, как люди говорят о "сфере видимости" переменной - это означает "где я могу использовать имя для ссылки на него".)
Итак, когда вы думаете о жизни статического массива, вы можете мысленно заменить:
int *subFunc(){
static int a[5] = {1,2,3,4,5};
return a;
}
с
int ONLY_USE_ME_INSIDE_SUBFUNC__a[5] = {1,2,3,4,5}; /* global variable */
int *subFunc(){
int * a = ONLY_USE_ME_INSIDE_SUBFUNC__a; /* a is the same as the global */
return a;
}
а затем притвориться, что никто другой в вашей программе не может коснуться этой глобальной переменной.
Ответ 4
Мне интересно, почему статические массивы не нужно освобождать?
-
Независимо от того, что не выделяется функцией управления памятью (malloc, calloc), например int a[5]
, не нужно явно обращаться за освобождением.
-
Статические переменные, такие как static int a[5]
, могут быть доступны в локальной области (они сохраняют свои значения между последующими вызовами локальной функции). Они созданы во время компиляции именно для этой цели, у них есть продолжительность жизни программы, поэтому было бы не логичным соображением, освобождающим их, даже если бы это было возможно, а это не так.
-
Все остальное мастерски объясняется в других ответах.
Ответ 5
Static variables
внутри функции, обычно используется для поддержки некоторых данных в области действия функции по нескольким вызовам для нее. Они инициализируются до main(), и их продолжительность жизни - это полное выполнение программы. Таким образом, это не имело бы смысла, если бы они были освобождены после выхода из функции. Если вы их бесплатно освободите, вы в следующий раз вызовете эту функцию, потому что на них не будут ссылаться.