Ответ 1
extern
необходим, поскольку он объявляет, что символ существует и имеет определенный тип, и не выделяет для него хранилище.
Если вы выполните:
int foo;
В файле заголовка, который делится между несколькими исходными файлами, вы получите ошибку компоновщика, потому что у каждого источника будет своя собственная копия foo, и компоновщик не сможет разрешить символ.
Вместо этого, если у вас есть:
extern int foo;
В заголовке он объявит символ, который определен в другом месте в каждом исходном файле.
Один (и только один) исходный файл будет содержать
int foo;
который создает один экземпляр foo для решения компоновщика.