При правильном использовании это может быть полезной техникой.
Допустим, у вас есть сложная, критичная к производительности подсистема с довольно небольшим общедоступным интерфейсом и большим количеством кода многократного использования. Код состоит из нескольких тысяч строк, сотен или около того приватных функций и совсем немного приватных данных. Если вы работаете с нетривиальными встроенными системами, вы, вероятно, сталкиваетесь с этой ситуацией достаточно часто.
Ваше решение, вероятно, будет многоуровневым, модульным и отделенным, и эти аспекты могут быть с пользой представлены и усилены путем кодирования различных частей подсистемы в разных файлах.
С этим вы можете многое потерять. Почти все наборы инструментов обеспечивают достойную оптимизацию для одного модуля компиляции, но очень пессимистично относятся ко всему объявленному extern.
Если вы поместите все в один исходный модуль C, вы получите -
Улучшения производительности и размера кода - во многих случаях вызовы функций будут встроены. Даже без включения компилятор имеет возможность создавать более эффективный код.
Данные уровня связи и скрытие функций.
Предотвращение загрязнения пространства имен и его следствия - вы можете использовать менее громоздкие имена.
Более быстрая компиляция и связывание.
Но вы также получаете безобразный беспорядок, когда дело доходит до редактирования этого файла, и вы теряете подразумеваемую модульность. Этого можно избежать, разделив исходный код на несколько файлов и включив их в один модуль компиляции.
Вам нужно навязать некоторые соглашения, чтобы правильно управлять этим. Это будет зависеть от вашего набора инструментов в некоторой степени, но некоторые общие указатели -
Поместите публичный интерфейс в отдельный заголовочный файл - вы все равно должны это делать.
Имеется один основной файл .c, который включает все вспомогательные файлы .c. Это также может включать код для открытого интерфейса.
Используйте средства защиты компилятора, чтобы убедиться, что частные заголовки и исходные модули не включены внешними модулями компиляции.
Все личные данные и функции должны быть объявлены как статические.
Сохранение концептуального различия между файлами .c и .h. Это использует существующие соглашения. Разница в том, что у вас будет много статических объявлений в заголовках.
Если ваша цепочка инструментов не навязывает никаких причин не делать этого, назовите частные файлы реализации как .c и .h. Если вы используете встроенные средства защиты, они не будут генерировать код и не будут вводить новые имена (вы можете получить пустые сегменты во время связывания). Огромным преимуществом является то, что другие инструменты (например, IDE) будут обрабатывать эти файлы соответствующим образом.