что это значит, когда в одном файле существует как объявление переменной, так и ее внешнее объявление?

Анализируя некоторые исходные коды, я обнаружил следующие определения в одном файле (.c), а не в другом файле (это один из кодов в файле, созданном с помощью flex, и нет включенного файла (stdio .h, string.h, errno.h, stdlib.h, inttypes.h), который определяет yyin):

extern FILE *yyin, *yyout;

FILE *yyin = (FILE*) 0, *yyout = (FILE *) 0;

Я в принципе знаю, что означают эти утверждения.

Но ключевое слово extern используется для использования таких определений, как переменная и функция, которые находятся в другом файле. (Он не выделяет для этого память.)

Итак, я имею в виду, что код:

FILE *yyin = (FILE*) 0, *yyout = (FILE *) 0;

должен появиться в другом файле, а не в том же файле.

Например,

a.c

extern File *yyin;  /* It means that a.c want to use yyin declared in b.c */

int main(void) {
   yyin = *expressions*; /* yyin is variable in b.c */

   return 0;
}

b.c

File *yyin = (FILE*) 0;

Почему они существуют в одном файле? Есть ли какие-то особые значения, когда ключевое слово extern и обычное объявление переменной с одним и тем же именем находятся в одном файле?


person user7159879    schedule 20.09.2017    source источник
comment
Если вы подумаете о том, как работает #include, вы поймете, что для единицы перевода с определением нормально иметь также объявление extern.   -  person M.M    schedule 20.09.2017


Ответы (1)


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

FILE *yyin, *yyout;

Напомним, что каждая переменная имеет область действия, продолжительность хранения и связь. Ключевое слово extern указывает, что переменная имеет внешнюю связь; другие варианты связывания - static, а не связывание.

Переменные могут иметь несколько объявлений. Пока несколько объявлений не конфликтуют друг с другом, компилятор C может их комбинировать.

В вашем случае переменные yyin и yyout имеют объявление, в котором говорится, что переменные имеют внешнюю связь, и определение, которое инициализирует обе переменные в NULL.

* Причина его эквивалентности в том, что нет других объявлений yyin и yyout. В общем, объявление без extern может стать определением, если в той же единице перевода не предусмотрено другое определение. Это называется предварительным определением. Объявление с extern не становится предварительным определением.

person Sergey Kalinichenko    schedule 20.09.2017
comment
Итак, в моем случае, хотя глобальная переменная имеет внешнюю связь по умолчанию, использование ключевого слова extern здесь явно означает, что оно явно указывает, что у нее есть внешняя связь. Я прав? - person user7159879; 20.09.2017
comment
@ user7159879 Верно. Это необычный способ объявить обычную глобальную переменную. - person Sergey Kalinichenko; 20.09.2017
comment
С extern и без _ - это не совсем одно и то же. Без extern это могло бы быть предварительное определение, а с extern - нет. - person Jens Gustedt; 20.09.2017
comment
@JensGustedt Вы правы, спасибо за записку. Я отредактировал ответ, чтобы включить объяснение. - person Sergey Kalinichenko; 20.09.2017