Подтвердить что ты не робот

Почему не нужно освобождать статические массивы?

Мне интересно, почему статические массивы не нужно освобождать? Я знаю, что при создании динамического массива, например.

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();
}

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

4b9b3361

Ответ 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(), и их продолжительность жизни - это полное выполнение программы. Таким образом, это не имело бы смысла, если бы они были освобождены после выхода из функции. Если вы их бесплатно освободите, вы в следующий раз вызовете эту функцию, потому что на них не будут ссылаться.