12

Как использовать extern для обмена переменными между исходными файлами?

10

Я знаю, что глобальные переменные в C иногда имеют ключевое слово extern. Что такое переменная extern? Каково её объявление? Каков её диапазон видимости?

Это связано с обменом переменными между исходными файлами, но как именно это работает? Где мне использовать extern?

5 ответ(ов)

1

Переменная с ключевым словом extern является декларацией (спасибо sbi за исправление) переменной, которая определена в другом объектном файле. Это означает, что память для этой переменной выделяется в другом файле.

Предположим, у вас есть два файла .c: test1.c и test2.c. Если вы определяете глобальную переменную int test1_var; в test1.c и хотите получить доступ к этой переменной в test2.c, вам нужно использовать extern int test1_var; в test2.c.

Вот полный пример:

// test1.c
int test1_var = 5;
// test2.c
#include <stdio.h>

extern int test1_var;

int main(void) {
    printf("test1_var = %d\n", test1_var);
    return 0;
}

Компилируйте оба файла и запускайте:

$ gcc test1.c test2.c -o test
$ ./test
test1_var = 5

Таким образом, используя extern, вы можете ссылаться на переменные, определенные в других файлах, что позволяет организовать код более гибко и избегать дублирования.

0

Ключевое слово extern используется для того, чтобы объявить, что переменная находится в другом объектном модуле (translation unit).

Это позволяет вам использовать переменную в одном объектном модуле и затем обращаться к ней из другого. В этом случае, во втором модуле вы объявляете переменную как extern, и значение будет разрешено компоновщиком (linker).

Если вы не объявите переменную как extern, у вас получится две переменные с одинаковыми именами, которые не будут связаны, что приведет к ошибке множественного определения переменной.

0

В вашем вопросе рассматриваются различия между декларацией, определением и инициализацией переменных в C/C++. Давайте разберем ваш пример.

                 declare | define   | initialize |
                ----------------------------------

extern int a;    yes          no           no
-------------
int a = 2019;    yes          yes          yes
-------------
int a;           yes          yes          no
-------------

Разбор таблицы:

  1. extern int a;

    • Декларация: Да
    • Определение: Нет
    • Инициализация: Нет
      В этом случае происходит лишь объявление переменной a, которая будет определена где-то еще (например, в другом файле). Память для переменной a не выделяется.
  2. int a = 2019;

    • Декларация: Да
    • Определение: Да
    • Инициализация: Да
      Здесь происходит как объявление переменной, так и выделение для неё памяти (определение). Переменной a присваивается значение 2019, что также является инициализацией.
  3. int a;

    • Декларация: Да
    • Определение: Да
    • Инициализация: Нет
      В этом случае переменная a объявляется и определяется, но ей не присваивается никакое значение (инициализация не производится). Память для неё выделяется, но её значение остается неопределённым.

Общий вывод: Декларация переменной не приводит к выделению памяти, пока переменная не будет определена. Определение же, как правило, ведёт к выделению памяти. Такой подход позволяет четко различать эти понятия, что очень важно при работе с переменными и ключевым словом extern.

0

Я люблю думать о переменной extern как о обещании, которое вы даете компилятору.

Когда компилятор встречает extern, он может определить только её тип, но не знает, где она "находится", поэтому не может разрешить это обращение.

Вы как бы говорите компилятору: "Доверься мне. Во время линковки это обращение будет разрешено."

0

extern говорит компилятору, что память для этой переменной объявлена где-то еще, поэтому он не будет пытаться выделять или проверять память.

Таким образом, вы можете скомпилировать файл, который ссылается на extern, но не сможете сделать линковку, если эта память не объявлена где-либо.

Это полезно для глобальных переменных и библиотек, но может быть опасно, так как линковщик не проводит проверку типов.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь