Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Язык C

Классы хранения в C: auto, register, static, extern — область видимости и время жизни

Что такое класс хранения?

Класс хранения (storage class) определяет:

  1. Область видимости (scope) — где в коде имя доступно.
  2. Время жизни (lifetime) — когда память выделяется и освобождается.
  3. Линковку (linkage) — видно ли имя другим файлам компиляции.
  4. Место хранения — стек, регистр, сегмент данных (BSS/DATA).

В C есть 4 класса хранения (плюс _Thread_local в C11):

1. auto (автоматический) — по умолчанию для локальных

void func() {
    int a;           // auto неявно
    auto int b;      // явно (редко используется)
}

Примечание: в C++11 auto означает «вывод типа», в C — только класс хранения.

2. register — подсказка для регистра процессора

void func() {
    register int counter = 0; // просьба положить в регистр
    for (int i = 0; i < 100; i++) counter += i;
}

3. static — статическое хранение

Два разных контекста — разное поведение:

А) static локальная переменная (внутри функции)

void counter() {
    static int count = 0; // инициализация ТОЛЬКО при первом вызове
    count++;
    printf("Call %d\n", count);
}

Б) static глобальная переменная / функция (вне функций)

// file1.c
static int internal_var = 42;     // видно ТОЛЬКО в file1.c
static void internal_func() {}    // внутренняя линковка

4. extern — внешняя линковка

Объявляет, что переменная/функция определена в другом файле.

Переменные

// main.c
int global_config = 100;          // определение (память выделена здесь)
extern void init_subsystem();     // объявление функции из другого файла

// subsystem.c
extern int global_config;         // объявление: используем ту же память
void init_subsystem() {
    global_config = 200;          // меняем общую переменную
}

Функции

По умолчанию функции имеют extern линковку. extern void foo(); и void foo(); эквивалентны. static void foo(); — внутренняя.

Сводная таблица

КлассКлючевое словоГде объявляетсяОбласть видимостиВремя жизниЛинковкаИнициализация по умолч.
Автоauto (неявно)БлокБлокБлокНетНеопределённо
РегистрregisterБлокБлокБлокНетНеопределённо
Статик (лок.)staticБлокБлокПрограммаНет0
Статик (глоб.)staticФайлФайлПрограммаВнутренняя0
ЭкстернexternФайл / заголовочникПрограммаПрограммаВнешняя0 (в определении)

Пример: многомодульный проект

// config.h
#ifndef CONFIG_H
#define CONFIG_H
extern int max_connections;      // объявление
extern const char *app_version;  // объявление
void config_init(void);
#endif

// config.c
#include "config.h"
int max_connections = 10;        // определение
const char *app_version = "1.0"; // определение
void config_init() { max_connections = 100; }

// main.c
#include <stdio.h>
#include "config.h"
int main() {
    config_init();
    printf("Max connections: %d, Version: %s\n", max_connections, app_version);
    return 0;
}

Компиляция: gcc main.c config.c -o app.

C11: _Thread_local

_Thread_local int thread_id = 0; // каждый поток имеет свою копию

Лучшие практики

Язык C

  1. Классы и объекты в C++: практическое руководство по объектно-ориентированному программированию
  2. Дружественные функции и классы в C++: мастерство контроля доступа
  3. Классы хранения в C: область видимости, время жизни и производительность
  4. Структуры C++ против классов: практическое руководство для разработчиков встроенных систем
  5. Мастерство метода str.count() в Python: как подсчитывать символы и подстроки с примерами
  6. Python list.count(): экспертное руководство с практическими примерами
  7. Java: объекты, классы и основные концепции ООП
  8. Классы хранения в C++: область видимости, время жизни и использование
  9. Интерфейсы в C++: абстрактные классы и чисто виртуальные функции
  10. Классы в C#: определение, конструкторы, деструкторы, статические члены