Функции в заголовках C? - PullRequest
0 голосов
/ 17 мая 2018

Я слышал, что вы помещаете прототипы функций в файлы заголовков, а затем помещаете определения функций в файл .c.Тем не менее, что это за файл .c.Например, если бы вы включили файл "foo.h", вы бы назвали вышеупомянутый файл .c "foo.c", поместили в него определение функции, поместили его в то же место, что и foo.h, иКогда вы попытаетесь включить foo.h, будет ли функция перенесена из файла c и будет ли она готова к использованию?

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

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

Вам необходимо скомпилировать foo.c отдельно в объектный файл (в случае Linux это файл .o).Например, используя команду -

gcc -c foo.c -o foo.o

Теперь этот foo.o должен быть связан с вашей реальной программой.Это можно сделать, просто передав объектный файл во время компиляции как

gcc test.c foo.o -o test.out

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

неопределенная ссылка на функцию foo_function.

0 голосов
/ 17 мая 2018

Заголовочные файлы просто обычные.Препроцессор C обрабатывает директиву #include s, и компилятор видит предварительно обработанный ввод (но вы можете скопировать и вставить огромное количество кода C, чтобы получить эквивалент #include),На самом деле препроцессору все равно, если вы #include "foo.h" или #include "foo.c", но последнее часто имеет плохой вкус.Наименование файлов заголовков с суффиксом .h является просто (очень распространенным) соглашением .

Так что, если у вас есть определение функции в заголовке, включенном в несколько исходных файлов (технически * 1014)* единица перевода с), что определение функции находится в каждой такой единице перевода.

Что произойдет тогда, зависит от определения этой функции (оно должно быть static или даже лучше static inline).

На практике вы должны ограничить определения функций в заголовке static или static inline.Если вы не объявите static определение функции void foo(int x) { /* something */ } в заголовке, который включен в несколько файлов *.c, у вас будет несколько определений ошибок foo во время ссылка времени.И основной интерес в размещении определения функции в заголовке - включение встраивания (отсюда подсказка inline);в противном случае (в обычном случае) вам это не нужно, и вы просто помещаете прототип функции в заголовочный файл, а определение функции - в один ваших *.c файлов.

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

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

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

Не забудьте включить все предупреждения и отладочную информацию. С GCC, используйте gcc -Wall -Wextra -g, возможно с -Wstrict-prototypes.Вы можете получить включенные файлы с -H (и предварительно обработанную форму с -C -E).

См. Некоторый C ссылочный сайт и стандарт C11 n1570 Больше подробностей.Прочитайте руководство GNU cpp о предварительной обработке.

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