Первое: перестаньте думать о глобальных переменных в C и C ++, иначе вы увековечите свое замешательство.Проблема более сложная, чем, например, в Python или Pascal, и поэтому вы не можете просто использовать одно слово для понятия (ов).
Во-вторых, нет «кучи» или «стека»- это сведения об операционной системе и процессоре, и они не имеют ничего общего с абстрактной спецификацией языка C ++.
Теперь переменные имеют 1) область действия, 2) связь и 3) класс хранения.Ключевое слово static используется для воздействия на все три аспекта, в зависимости от того, где вы его используете.
Область действия : где объявлена переменная.Если внутри функции, это область действия функции, если за пределами функции это область действия файла (то, что вы, вероятно, называете «глобальной переменной»).
Linkage :доступна ли переменная из других модулей компиляции (актуально, когда ваша программа состоит из нескольких исходных файлов).
Класс хранения :
Статические переменныераспределяются в порядке, определяемом реализацией, при запуске программы и живут до завершения программы.Они не могут быть «освобождены» или «перераспределены».(типичной реализацией являются сегменты BSS и DATA, как уже упоминали другие).
Автоматические переменные существуют только в области действия функции, они распределяются (и, возможно, инициализируются) при входе в функцию (обычно вСтек процессора) и освобождается при выходе из функции.
Динамический класс хранения - это то, что вы, вероятно, называете «кучей».Это переменные, чье хранение напрямую управляется через malloc / free или new / delete.Хранилище для статических переменных управляется ОЧЕНЬ иначе, чем динамическое хранилище, и два вида хранилища принципиально несовместимы.
Пример:
===
// ALL file-scope variables have static storage class
int global1; // file-scope, external linkage
static int global2; // file-scope, internal linkage
void f()
{
static int x; // static storage class, function-scope
int y; // automatic storage class, function-scope
free(&x); // ILLEGAL, WILL CRASH!
free(&y); // DITTO!
free(&global1); // DITTO!
}
===
Теперь все переменные со статическим классом хранилища(global1, global2 и x) выделяются и инициализируются перед запуском программы.Если вы не укажете начальные значения, они будут инициализированы по умолчанию в НЕУКАЗАННОМ ПОРЯДКЕ.(Для примитивных типов это просто означает заполнение нулями).
Статические переменные освобождаются только при выходе из программы.Это означает, что «x» в функции f будет инициализировано ТОЛЬКО ОДИН РАЗ (при запуске программы) и что он ОСТАВЛЯЕТ ЕГО ЗНАЧЕНИЕ между вызовами функции (в отличие от y, который будет выделен для каждой записи функции и освобожден для каждой функции).выход, таким образом, также его значение уничтожено).Обратите внимание, что использование статических переменных внутри функций очень несовместимо с многопоточностью и повторным входом, если вы очень хорошо знаете, что делаете.