Какая разница между использованием extern и #include файлов заголовков?

Я начинаю сомневаться в полезности ключевого слова "extern", которое используется для доступа к переменным/функциям в других модулях (в других файлах). Разве мы не делаем то же самое, когда мы используем препроцессор #include для импорта файла заголовка с прототипами переменных/функций или определениями функций/переменных?

Ответы

Ответ 1

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

Если вы выполните:

int foo;

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

Вместо этого, если у вас есть:

extern int foo;

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

Один (и только один) исходный файл будет содержать

int foo;

который создает один экземпляр foo для решения компоновщика.

Ответ 2

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