extern и связывание
Делитесь символами между файлами.
«extern и связывание» — бесплатный урок C Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C Academy содержит 4 уроков всего.
Что такое связывание
Связывание описывает, может ли имя использоваться совместно в разных исходных файлах.
Имя с внешним связыванием обозначает одну и ту же сущность во всей программе. Имя с внутренним связыванием доступно только в собственном файле. Понимание связывания необходимо для программ из нескольких файлов.
Совместное использование переменной
Предположим, двум файлам нужен доступ к одному глобальному счётчику. Нельзя просто определить его в обоих файлах: так создаются две отдельные переменные и возникает ошибка компоновки из-за дублирующегося символа.
Вместо этого определите его один раз, а во всех остальных местах объявите с помощью extern.
/* config.c */
int g_count = 0; /* the one definition */Ключевое слово extern
extern сообщает компилятору, что переменная существует где-то ещё в программе, не выделяя для неё память здесь.
Это чистое объявление. Позже компоновщик связывает его с единственным определением в другом файле.
/* other.c */
extern int g_count; /* declared, not defined */
void bump(void) {
g_count++;
}Объявление в заголовочном файле
Правильный шаблон таков: поместите объявление extern в заголовочный файл, а соответствующее определение — ровно в один исходный файл.
После этого любой файл, подключающий заголовок, сможет использовать общую переменную.
/* config.h */
#ifndef CONFIG_H
#define CONFIG_H
extern int g_count;
#endifОдно определение, много объявлений
Это правило одного определения для глобальных объектов: переменную можно объявить с extern во многих файлах, но определить только в одном.
Единственное определение (без extern) выделяет память. Все объявления с extern лишь указывают на неё.
/* config.h */ extern int g_count; /* declaration */
/* config.c */ int g_count = 0; /* definition */Функции тоже имеют внешнее связывание
По умолчанию функции также имеют внешнее связывание, поэтому прототип в заголовочном файле позволяет другим файлам вызывать их.
Перед прототипом можно написать extern, но это избыточно: функции являются внешними, если явно не указано обратное.
/* both forms mean the same */
int add(int a, int b);
extern int add(int a, int b);Внутреннее связывание с static
Ключевое слово static на уровне файла задаёт для имени внутреннее связывание: оно видно только внутри собственного исходного файла.
Используйте его для вспомогательных функций и глобальных объектов, которые должны оставаться частными для модуля. Другие файлы не могут их видеть или конфликтовать с ними.
/* parser.c */
static int line_no = 0; /* private to parser.c */
static void advance(void) { /* private helper */
line_no++;
}extern и static
Эти два ключевых слова находятся на противоположных концах спектра связывания.
extern запрашивает внешнее связывание: сделать это имя общим для нескольких файлов. static на уровне файла принудительно задаёт внутреннее связывание: оставить это имя частным. Грамотный выбор определяет, что именно предоставляет ваш модуль.
extern int shared_total; /* visible everywhere */
static int local_cache; /* only this file */Распространённая ошибка
Начинающие иногда помещают обычное определение, например int g_count;, в заголовочный файл.
Поскольку заголовок подключается в нескольких файлах, каждый файл получает собственное определение, и компоновщик сообщает о дублирующемся символе. Всегда объявляйте переменную с extern в заголовочном файле, а определяйте один раз в файле .c.
/* WRONG in a header included twice */
int g_count; /* multiple definition */
/* RIGHT */
extern int g_count; /* declaration only */Собираем всё вместе
Такая структура из трёх файлов — стандартный способ совместно использовать состояние.
Заголовок объявляет переменную, один исходный файл определяет её, а остальные используют после подключения заголовка. Компоновщик объединяет все ссылки с единственным определением.
/* config.h */ extern int g_count;
/* config.c */ #include "config.h"
int g_count = 0;
/* main.c */ #include "config.h"
/* uses g_count */Примечание об инициализации
Начальное значение должно задаваться только в настоящем определении: int g_count = 0;.
Объявление extern не должно выполнять инициализацию, поскольку оно не выделяет память. Запись extern int g_count = 0; превращает её в определение и лишает смысл сам подход.
extern int g_count; /* ok: declaration */
extern int g_count = 0; /* becomes a definition */Быстрая проверка
Проверьте, насколько хорошо Вы понимаете extern и связывание.
Повторение
Вы узнали, что связывание управляет видимостью между файлами. extern объявляет имя, определённое в другом месте; static на уровне файла делает имя частным.
Используйте глобальные переменные совместно с одним определением и объявлениями extern. Далее Вы скомпилируете и скомпонуете эти файлы в программу.
Часто задаваемые вопросы
Урок «extern и связывание» бесплатный?
Да — полный текст урока «extern и связывание» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C Academy, подпишись на CoddyKit PRO. Курс C Academy содержит 4 уроков всего.
Чему я научусь в уроке «extern и связывание»?
Делитесь символами между файлами. Ты практикуешь C Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C Academy?
Предыдущий опыт не требуется. C Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «extern и связывание»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C Academy?
Да. Каждый урок C Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Заголовочные и исходные файлы
- Защита заголовков
- extern и связывание
- Компиляция нескольких файлов