У комп'ютерному програмуванні стати́чна змі́нна (англ. static variable) — це змінна, пам'ять під яку було виділено «статично», що означає, що її час існування[en] (англ. lifetime, або англ. extent) — це все виконання програми. Це відрізняється від коротковічніших автоматичних змінних[en], пам'ять під які розподіляється в стеку[en] й звільняється в стеку викликів, й від об'єктів, пам'ять під які динамічно виділяється та звільняється в купі.

Час існування змінної[en] протиставляється області видимості (де змінну можливо використовувати): «глобальна» та «локальна» стосується області, а не часу існування, але з області часто випливає час існування. У багатьох мовах глобальні змінні завжди статичні, але в деяких мовах вони динамічні, тоді як локальні змінні, як правило, автоматичні, але можуть бути статичними.

В загальному сенсі, стати́чне виділя́ння па́м'яті (англ. static memory allocation) — це виділяння пам'яті під час компілювання[en], до виконання пов'язаної програми, на відміну від динамічного або автоматичного[en] виділяння пам'яті, коли пам'ять розподіляється відповідно до потреб під час виконання[en].[1]

ІсторіяРедагувати

Статичні змінні сходять принаймні до ALGOL 60[en] (1960 р.), де вони відомі як власні змінні (англ. own variables):

Оголошення може бути позначено додатковим описувачем own (укр. власний). Це має наступний ефект: при повторному вході до блоку значення власних величин будуть незмінними порівняно з їхніми значеннями з попереднього виходу, тоді як значення оголошених змінних, не позначених власними, невизначені.
— Revised report on ALGOL 60, section "5. Declarations", p. 14 (англ.)

Це визначення дещо відрізняється від статичної змінної: воно лише визначає поведінку, а відтак, тривалість існування, а не зберігання: пам'ять під власну змінну може бути виділено, наприклад, під час першого виклику функції, а не під час завантаження програми.

Використання слова static для позначення цих змінних сходить щонайменше до BCPL (1966 р.), і було популяризоване мовою програмування C, на яку сильно вплинула BCPL. Визначення BCPL звучить так:

(1) Статичні елементи даних:
Елементи даних, час існування яких триває стільки же, скільки й час виконання програми; такі елементи даних мають явні сталі L-значення. Кожен статичний елемент даних мусить бути оголошено у визначенні функції або підпрограми, у глобальному оголошенні, або як мітку, встановлену двокрапкою.
— The BCPL Reference Manual, 7.2 Space Allocation and Extent of Data Items (англ.)

Зауважте, що BCPL позначала через «динамічний елемент даних» те, що зараз називають автоматичною змінною (локальною, пам'ять під яку виділяється в стеку), а не об'єкти, пам'ять під які виділяється в купі, що для них використовують термін динамічне виділяння зараз.

Ключове слово static[en] використовують в C та споріднених мовах як для статичних змінних, так і для інших понять.

АдресуванняРедагувати

Режим адресування абсолютними адресами можливо використовувати лише зі статичними змінними, оскільки це єдиний тип змінних, розташування яких відоме компілятору під час компілювання. Коли програма (виконуваний файл або бібліотека) завантажується[en] до пам'яті, статичні змінні зберігаються в сегменті даних[en] адресного простору[en] програми (ініціалізовані), або в сегменті BSS (не ініціалізовані), а до завантаження зберігаються у відповідних розділах об'єктних файлів.

Область видимостіРедагувати

З точки зору області видимості та часу існування[en], статичні змінні мають за час існування все виконання програми, але можуть мати обмеженішу область видимості. Основна відмінність пролягає між статичною глобальною змінною (англ. static global variable), яка має глобальну область видимості й відтак знаходиться в контексті всієї програми, та статичною локальною змінною (англ. static local variable), область видимості якої локальна. Статична локальна змінна відрізняється від локальної змінної тим, що статична локальна змінна ініціалізується лише один раз, незалежно від того, скільки разів викликають функцію, в якій вона перебуває, і її значення зберігається й доступне протягом багатьох викликів функції, в якій її оголошено, наприклад, для використання як змінної лічильника. Статична змінна також може мати область видимості модуля[en] або якийсь інший варіант, наприклад внутрішнє зв'язування[en] в C, що є різновидом області видимості файлу або області видимості модуля.

ПрикладРедагувати

Приклад статичної локальної змінної в C:

#include <stdio.h>

void Func() {
  static int x = 0;
  // |x| ініціалізується лише один раз за всі п'ять викликів |Func| і ця змінна
  // після цих викликів збільшиться п'ять разів. Кінцевим значенням |x|
  // буде 5.
  x++;
  printf("%d\n", x);  // виводить значення |x|
}

int main() {
  Func();  // друкує 1
  Func();  // друкує 2
  Func();  // друкує 3
  Func();  // друкує 4
  Func();  // друкує 5

  return 0;
}

Об'єктно-орієнтоване програмуванняРедагувати

В об'єктно-орієнтованому програмуванні також існує поняття статичної змінної-члена[en] (англ. static member variable), яка є «змінною класу[en]» (англ. "class variable") статично визначеного класу, тобто змінною-членом[en] даного класу, що є спільною для всіх примірників[en] (об'єктів), і доступна як змінна-член цих об'єктів. Пам'ять для змінної класу динамічно визначеного класу в мовах, де класи можливо визначати під час виконання, виділяється при визначанні класу, і не є статичною.

Пам'ять під об'єктні сталі, відомі під час компілювання, такі як стрічкові літерали[en], зазвичай виділяється статично. В об'єктно-орієнтованому програмуванні пам'ять під таблиці віртуальних методів класів зазвичай виділяється статично. Статично визначене значення також може бути глобальним у своїй області видимості, що забезпечує використання того самого незмінного значення протягом виконання для цілісності.

Див. такожРедагувати

ПриміткиРедагувати

  1. Jack Rons. What is static memory allocation and dynamic memory allocation?. MeritHub [An Institute of Career Development]. Архів оригіналу за 19 травня 2011. Процитовано 16 червня 2011. «Компілятор виділяє необхідне місце в пам'яті для оголошеної змінної. Зарезервована адреса отримується з допомогою оператора addressof, і її може бути записано до вказівникової змінної. Оскільки більшість оголошених змінних мають статичну пам'ять, цей спосіб записування вказівникового значення до вказівникової змінної відомий як статичне виділяння пам'яті. Пам'ять призначається під час компілювання.»  (англ.)

ДжерелаРедагувати