Как вы связываете .c и .h файлы с тем же именем? - PullRequest
4 голосов
/ 07 июня 2009

При чтении исходного кода библиотеки я вижу, что существуют файлы .c и .h с одинаковыми именами. В основной источник включен файл .h, но не файл .c. Когда я смотрю на код в файле .h, он также не #include файл .c с тем же именем. Я что-то пропустил? Включает ли компилятор автоматически файл .c, если файл с именем .h с тем же именем #include 'd?

Ответы [ 7 ]

8 голосов
/ 07 июня 2009

Нет магии. Когда программа на С компилируется, есть два основных шага к ней.

Во-первых, каждая отдельная единица компиляции находится в изоляции. (Единица компиляции - это один файл .c плюс все, что в него входит).

На данном этапе он ничего не знает о том, что содержится в других файлах .c, что означает, что он не может создать полную программу. Что он может сделать, так это сгенерировать код с несколькими точками «заполнить пробелы». Если из foo.c вы вызываете функцию, которая объявлена ​​в bar.h и определена в bar.c, то компилятор может только видеть, что функция существует. Он объявлен в bar.h, поэтому мы должны предположить, что полное определение существует где-то . Но поскольку это определение находится внутри другого модуля компиляции, мы пока не можем его увидеть. Таким образом, компилятор генерирует код для вызова функции, с небольшим примечанием о том, что «введите адрес этой функции, как только она станет известна».

После того, как каждый модуль компиляции будет скомпилирован таким образом, у вас останется куча объектных файлов (обычно .o, если скомпилирована GCC, и .obj, если вы используете MSVC), содержащих этот вид «заполнения пробелов». "код.

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

Так что ничего особенного не происходит, если файл .c имеет то же имя, что и .h. Это просто соглашение, чтобы людям было проще выяснить, что находится внутри каждого файла.

Компилятору все равно. Он просто берет каждый файл .c плюс все, что он включает, и компилирует его в объектный файл. Затем компоновщик объединяет все эти объектные файлы в один исполняемый файл.

8 голосов
/ 07 июня 2009

Типичные .h файлы служат «оглавлением» для файла .c, включая такие вещи, как прототипы функций, typedefs и тому подобное. Программы включают .h, чтобы они знали о функциях и типах.

Файлы .c компилируются отдельно и создают объектные файлы (.o или .obj), которые содержат фактический код.

Затем объектные файлы привязываются к основной программе с помощью файла Makefile, файла Project или аналогичного метода. Затем объектные файлы связываются с основной программой, образуя функциональное целое.

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

6 голосов
/ 07 июня 2009

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

Обычно это что-то вроде:

"a.c"    includes   "a.h"
"b.c"    includes   "c.h"

Вы компилируете "a.c" и "b.c" и связываете выходные файлы.

4 голосов
/ 07 июня 2009

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

Каждый из .c-файлов компилируется в объектный файл, и все эти объектные файлы затем объединяются в библиотеки или приложения.

1 голос
/ 07 июня 2009

В вашем вопросе есть что-то неправильное. Вы компилируете файлы * .h и, не обращая внимания на встроенные ссылки, ссылаетесь на файлы * .c.

Если вы вернетесь к основам, вы можете сказать, что:

  • файл ".h" - это ваш интерфейс к библиотеке, то есть то, с чем вы должны компилироваться, и
  • соответствующий * .c файл является реализацией того, что вы намереваетесь сделать функцией.

Итак, в качестве примера:

  1. файл add_integers.h просто объявляет функцию, скажем, addInts (), которая принимает два целых числа и возвращает целое число, которое является суммой двух, и
  2. файл add_integers.c (pp) обеспечивает реализацию функции addInts (), которая использует алгоритм, который принимает два целых числа, складывает их вместе и возвращает результаты.

Разработчик функции addInts () может вносить изменения в программное обеспечение, реализующее функцию addInts ().

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

Вау! Почему чтение этого объяснения звучит как Дэнни Кэй и " Сосуд с мочалкой "?

Возможно, вам захочется взглянуть на работу Бертрана Мейера с Эйфелевой и " Дизайн по контракту ".

1 голос
/ 07 июня 2009

Препроцессор не делает ничего волшебного.

Чтобы включить что-то во включенный каталог (сложно сделать с вашими собственными заголовками)

#include <foo.h>

или включить что-либо в тот же каталог компиляции

#include "foo.h"

Все, что он делает, это берет текст foo.h и подключает его непосредственно к выводу. gcc a.c -E выведет, как он выглядит после предварительной обработки.

Это «глупый» процесс, когда написание собственной программы, которая будет правильно обрабатывать #include, является тривиальным упражнением.

0 голосов
/ 10 июня 2009

Если я хочу создать статическую библиотеку на C или C ++, я помещу свои прототипы функций в .h и фактические коды функций в .c или .cpp. После этого я скомпилировал свой .cpp для создания .lib

Чтобы связать мой .h с моим .lib, я пишу эту команду препроцессора в .h

#pragma comment (lib, "theNameOfTheLibFile.lib")

После этого, если я включу .h в программу, моя программа будет знать, где найти соответствующую библиотеку.

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