Насколько я помню стандарт, все объявления функций по умолчанию считаются "extern" , поэтому нет необходимости указывать его явно.
Это не делает это ключевое слово бесполезным, поскольку его также можно использовать с переменными (и в этом случае - это единственное решение для решения проблем с сцеплением). Но с функциями - да, это необязательно .
Немного более подробный ответ заключается в том, что он позволяет вам использовать переменные, скомпилированные в другом файле исходного кода, но не резервирует память для этой переменной. Таким образом, чтобы использовать extern, вы должны иметь файл исходного кода или библиотечный модуль, который содержит пространство памяти для переменной верхнего уровня (не внутри функций). Теперь вы можете обратиться к этой переменной, определив переменную extern с тем же именем в других файлах исходного кода.
В целом, следует избегать использования внешнего определения. Они легко приводят к неуправляемому коду и ошибкам, которые трудно обнаружить. Конечно, есть примеры, когда другие решения были бы непрактичными, но они редки. Например, stdin и stdout - это макросы, которые отображаются в переменную внешнего массива типа FILE * в stdin.h; пространство памяти для этого массива находится в стандартном модуле C-библиотеки.