Сомнения, связанные с использованием внешних ключевых слов - PullRequest
1 голос
/ 27 февраля 2010

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

extern int i = 10;

Должен ли компилятор пометить ошибку для того же самого? Я видел, как некоторые компиляторы были терпимы и игнорировали это? Почему это так? Что говорит об этом стандарт «С»?

РЕДАКТИРОВАТЬ: @All, спасибо за ответы. У меня все еще есть сомнения. Предположим, у меня есть определение для этой переменной без внешней ссылки в другом файле, скажем, a.c, и я добавляю это утверждение в b.c. Все еще нормально для компилятора, чтобы не отмечать ошибку? Подходит ли переопределение?

Ответы [ 4 ]

5 голосов
/ 27 февраля 2010

Это правильный синтаксис, в стандарте C99 есть даже практически идентичный пример. (См. §6.9.2-4.)

Это правда, что примеры не являются нормативными, но я считаю, что это был заданный законный синтаксис. Компилятор часто выводит предупреждение, потому что на самом деле он ничего не выполняет.

4 ПРИМЕР 1

int i1 = 1;             // definition, external linkage
static int i2 = 2;      // definition, internal linkage
extern int i3 = 3;      // definition, external linkage
int i4;                 // tentative definition, external linkage
static int i5;          // tentative definition, internal linkage
int i1;                 // valid tentative definition, refers to previous
int i2;                 // 6.2.2 renders undefined, linkage disagreement
int i3;                 // valid tentative definition, refers to previous
int i4;                 // valid tentative definition, refers to previous
int i5;                 // 6.2.2 renders undefined, linkage disagreement
extern int i1;          // refers to previous, whose linkage is external
extern int i2;          // refers to previous, whose linkage is internal
extern int i3;          // refers to previous, whose linkage is external
extern int i4;          // refers to previous, whose linkage is external
extern int i5;          // refers to previous, whose linkage is internal
4 голосов
/ 28 февраля 2010

следующий код;

extern int i ;

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

Однако ваш пример:

extern int i = 10 ;

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

extern int i ;  // redundant
int i = 10 ;

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

Вы можете проверить это следующим образом:

extern int i ;
int main()
{
    i = 10 ;
}

Вышеуказанное приведет к ошибке компоновщика для неразрешенной переменной i. Принимая во внимание:

extern int i = 10 ;
int main()
{
    i = 10 ;
}

свяжется без проблем.

0 голосов
/ 27 февраля 2010

Цель ключевого слова extern - дать сущности внешнюю связь .Используется ли оно в объявлении в или определении, не имеет значения.Там нет абсолютно никаких ошибок в коде, который вы опубликовали.

Если вы предпочитаете думать об этом с точки зрения «экспорт против импорта», тогда ключевое слово extern применяется к неопределяющему объявлению означает, что мы импортируем сущность, определенную в некоторой другой единице перевода.Когда ключевое слово extern применяется к определению , это означает, что мы экспортируем эту сущность для использования другими единицами перевода.(Хотя стоит отметить, что «экспорт против импорта» - это не совсем стандартный подход к концепции связи С).

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

extern int i = 10;

является действительным, но избыточным, поскольку оно эквивалентно обычному

int i = 10;

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

extern void foo(int i); /* `extern` is superfluous */
...
extern void foo(int i) /* `extern` is superfluous */
{
  /* whatever */
}
0 голосов
/ 27 февраля 2010

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

...