внешние и глобальные переменные с одинаковыми именами в C

Я пытаюсь понять, что произойдет, если в какой-то программе у нас будет так:

extern int x;

void foo(){...}
void bar(){...}

void main(){
foo();
bar();
}
int x=0;

Так что же должно произойти? Почему разрешено иметь две такие переменные с одинаковыми именами? Они разные?


person ChikChak    schedule 08.02.2017    source источник
comment
Попробуйте скомпилировать: int x; int x; int x = 3; extern int x;. Даже с очень суетливыми параметрами, установленными для GCC, он компилируется. Переместите строку extern наверх, и clang -Weverything примет ее. Первые два int x; являются предварительными определениями. int x = 3; — это не предварительное (окончательное?) определение. Вы не могли повторить это или использовать другой инициализатор. Если бы к концу файла не было окончательного определения, int x; было бы преобразовано в одно.   -  person Jonathan Leffler    schedule 09.02.2017
comment
Переменная, объявленная в области файла без спецификатора класса хранения, имеет тот же класс хранения и связь, что и явно объявленная extern. То есть нет никакой разницы между переменными, которые вы называете внешними, и переменными, которые вы называете глобальными. Однако наличие или отсутствие extern может иметь значение и в других отношениях.   -  person John Bollinger    schedule 09.02.2017


Ответы (3)


Это не «две» переменные. Они одинаковые.

extern int x;

является объявлением x.

а также

int x=0;

обеспечивает определение для x. Это совершенно нормально и справедливо.


У вас может быть несколько объявлений, например:

extern int x;
extern int x;

тоже, и он тоже скомпилируется.

Обратите внимание, когда вы предоставляете несколько объявлений для одного и того же идентификатора, правила несколько сложны. Подробнее см. в разделе 6.2.2 Связи идентификаторов. В качестве примера см. статическое объявление m следует за нестатическим объявлением.

person P.P    schedule 08.02.2017

Прекрасно. Этот

extern int x;

только объявляет переменную x типа int, а extern явно говорит, что она будет определена в другом месте.

В вашем случае, несколькими строками ниже

int x = 0;

Вот ссылка для получения дополнительной информации о extern -> http://en.cppreference.com/w/cpp/language/storage_duration

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

person Alex    schedule 08.02.2017

"extern" означает:
"эта переменная будет взята из какого-то другого места. Здесь она не объявляется; этот оператор просто сообщает, что это допустимое имя."

Итак, по сути, этот код:

extern int x;
// This is a valid name, but the variable will be defined "externally", eg, somewhere else.

[...] 

int x=0;
// OH!  Here is where the definition is.  Now we know where that "extern" variable came from.
// And we know that it starts with value 0.

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

Как правило, определение находится в одном файле .C, а extern — в другом .C, которые будут связаны друг с другом в процессе сборки.

person abelenky    schedule 08.02.2017
comment
чаще всего extern находится в заголовочном файле - person M.M; 09.02.2017