Зачем мне объявлять глобал как `extern`, если я хочу его использовать? - PullRequest
1 голос
/ 17 мая 2019

Я понимаю, что переменные области файла в C по умолчанию extern - даже если это не указано явно (как объяснено в этом ответе на Глобальные переменные в C являются статическими или нет? ).

Однако я также знаю, что если a.h объявлен extern int x = 10; и b.c хочет получить доступ к x, ему необходимо объявить его как extern.

Почемуэто так?Почему бы просто не получить доступ к x без каких-либо дополнительных вещей extern?Каково техническое объяснение этого механизма?

Ответы [ 3 ]

1 голос
/ 17 мая 2019

Память для глобальной переменной выделяется только один раз. Например, в main.c:

int gMyCounter;

В любом другом модуле (C-файл), где вы хотите использовать или обрабатывать эту переменную, вы должны сообщить компилятору о ее существовании и типе. Это делается с помощью ключевого слова extern, например, mymodule.c:

extern int gMyCounter;

Во время компоновки компоновщик видит, что mymodule.o нужна переменная gMyCounter, и ищет ее в других файлах .o и библиотеках. Он находит это в main.o.

1 голос
/ 17 мая 2019

Поскольку переменная является внешней по отношению к файлу;он определен в другом файле, и вы просто указываете этому файлу, что он существует, но он не найдет его там.Тогда задача компоновщика - решить эту проблему.

Пример:

// a.c
int x = 7;

ac имеет переменную, определенную

// a.h
extern int x;

ah знает, что переменная существует,но он не знает где.Любой файл, содержащий ах, получит эти знания

// b.c
#include "a.h"

bc, поскольку он включает ах, теперь знает, что переменная х существует, но не знает, где.

компоновщикбудет разрешать эти различные использования одной и той же переменной х.Лучше быть такими же, иначе будут проблемы.

Вы можете солгать ах и написать float вместо int, и только компоновщик может заметить это, потому что компилятор буквально не имеетзнание о AC (ну, AC должен включать в себя ах, так что он заметит, но вы могли бы лгать ему, если вы не включите его)

Во всем проекте должен быть один и только один неэкстерьеропределение каждой переменной.0 или 2 или более, и компоновщик сообщит об ошибке.

0 голосов
/ 17 мая 2019

Заголовочный файл a.h не должен содержать

extern int x = 10;

но только

extern int x;

Тогда файл a.c должен определить

int x = 10;

и когда файл b.c хочет использовать x, он должен просто

#include "a.h"

и компилятор при компиляции b.c будет знать, что x определен где-то еще, и компоновщик найдет ссылку и исправит ее.


Из добавленной ссылки отредактируйте: если определение находится в модуле компиляции, который не виден компилятором, тогда переменная не может волшебным образом стать доступной: вам нужно объявить ее как extern там, где может видеть компилятор, чтобы он знал, что он будет доступно. Он служит примерно той же цели, что и прототип функции: это делерация, а не определение.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...