Есть ли принципиальная разница между исходными и заголовочными файлами в C? - PullRequest
38 голосов
/ 14 августа 2010

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

Пока что из-за отсутствия понимания, когда я писал библиотеки, я разбил весь класс и код метода класса на один файл, не зная, как выбрать расширение.

Что должно быть в заголовках и что должно быть в исходных файлах? Как мне реализовать это разделение?

Ответы [ 4 ]

61 голосов
/ 14 августа 2010

Нет технической разницы.Компилятор с радостью позволит вам включить файл .c или скомпилировать файл .h напрямую, если хотите.

Однако существует огромная культурная разница:

  • Объявления (прототипы) помещаются в .h файлы.Файл .h представляет собой интерфейс для всего, что реализовано в соответствующем файле .c.

  • Определения входят в .cфайлы.Они реализуют интерфейс, указанный в файле .h.

Разница в том, что файл .h может (и обычно будет) иметь значение #include dв несколько блоков компиляции (.c файлов).Если вы определите функцию в файле .h, она окажется в нескольких файлах .o, и компоновщик будет жаловаться на несколько определенный символ.Вот почему определения не должны идти в .h файлах.(Встроенные функции являются исключением.)

Если функция определена в файле .c, и вы хотите использовать ее из других файлов .c, объявление этой функции должно быть доступно в каждомиз этих других .c файлов.Вот почему вы помещаете объявление в .h и #include в каждом из них.Вы также можете повторить объявление в каждом файле .c, но это приводит к большому дублированию кода и непоправимому беспорядку.

Если функция определена в файле .c, но вы не't хотите использовать его из других .c файлов, нет необходимости объявлять его в заголовке.По сути, это деталь реализации этого .c файла.В этом случае сделайте также функцию static, чтобы она не конфликтовала с функциями с одинаковыми именами в других файлах.

14 голосов
/ 14 августа 2010

Что должно быть в заголовках и что должно быть в исходных файлах?

Обычно заголовки содержат одно или несколько из следующих значений:

  • Объявление функции (кроме статики)
  • Объявление переменной (обычно глобальное)
  • Объявление определенного пользователем типа (читать struct, union и т. Д.)
  • Макро определение

Исходные файлы с другой стороны имеют:

  • Определение функции / переменной
  • Объявление и определение статической функции (вы не хотите показывать их своим клиентам)
  • Определение переменной
  • Некоторые предпочитают определять встроенные функции (C99) в заголовке

Как мне реализовать это разделение?

Правило единого определения - ваш друг.

Помните, если вы пишете библиотеку, это то, что видит ваш клиент. Так что будьте полезны и предоставьте всю информацию, которую вы можете использовать для своей библиотеки. Исходные файлы обычно компилируются и поставляются в двоичном виде.

И, кстати, у C нет понятия классов.

2 голосов
/ 14 августа 2010

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

Итак, если в исходном файле A.c вам нужна функция, реализованная в исходном файле B.c, вы просто включаете B.h для ее объявления.

1 голос
/ 14 августа 2010

Существует небольшая принципиальная разница между файлами .c и .h (хотя некоторые компиляторы могут отказаться от компиляции необработанного файла .h). Разница больше по соглашению.

Обычно файл .h предоставляет API, а .c - реализацию.

Поэтому файл .h будет содержать только то, что нужно другим исходным файлам для доступа к средствам, предоставляемым вашим файлом .c. Таким образом, файлы .h предоставят прототипы функций глобальных функций, объявления глобальных переменных (если они вам действительно нужны), а также используемые ими структуры и другие типы. (Не раскрывайте структуру, если API требует только указатель на структуру.)

Встроенные функции также часто включаются в файлы .h, но некоторые рекомендации по кодированию предпочитают использовать отдельное расширение (например, .inl)

Все другие реализации функций, определения и инициализации переменных и объявления локальных (статических) переменных и функций будут в файле .c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...