0Pricing
C Academy · Урок

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 — локальная установка не требуется.

Все уроки этого курса

  1. Заголовочные и исходные файлы
  2. Защита заголовков
  3. extern и связывание
  4. Компиляция нескольких файлов
← Назад к C Academy