Включая один исходный файл C в другой?

Это нормально (или даже рекомендуется/хорошая практика) для #include файла .c в другом файле .c?

Ответ 1

Используется правильно, это может быть полезной техникой.

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

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

С помощью C вы можете много потерять, сделав это. Практически все инструментальные средства обеспечивают достойную оптимизацию для одного блока компиляции, но очень пессимистично относятся к чему-либо объявленному extern.

Если вы поместите все в один исходный модуль C, вы получите -

  • Улучшения производительности и размера кода - во многих случаях вызовы функций будут встроены. Даже без инкрустации компилятор имеет возможности для создания более эффективного кода.

  • Скрыть данные и функции уровня канала.

  • Избежание загрязнения пространства имен и его следствие - вы можете использовать менее громоздкие имена.

  • Более быстрая компиляция и связь.

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

Вам нужно наложить некоторые соглашения, чтобы правильно управлять этим. В какой-то степени они будут зависеть от вашей инструментальной цепочки, но некоторые общие указатели -

  • Поместите открытый интерфейс в отдельный файл заголовка - вы все равно должны это делать.

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

  • Используйте средства защиты компилятора, чтобы частные заголовки и исходные модули не были включены внешними единицами компиляции.

  • Все личные данные и функции должны быть объявлены статическими.

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

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

Ответ 2

это нормально? да, он скомпилирует

рекомендуется? файлы no -.c компилируются в файлы .obj, которые связаны после компиляции (компоновщиком) в исполняемый файл (или библиотеку), поэтому нет необходимости включать один файл .c в другой. Вместо этого вы, скорее всего, захотите сделать файл .h, в котором перечислены функции/переменные, доступные в другом .c файле, и включить файл .h

Ответ 3

Нет.

В зависимости от вашей среды сборки (вы не укажете) вы можете обнаружить, что она работает именно так, как вы хотите.

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

Как правило, эту практику следует избегать.

Если вам абсолютно необходимо # включить источник (и, как правило, его следует избегать), используйте другой файл суффикса для файла.

Ответ 4

Я думал, что поделюсь ситуацией, когда моя команда решила включить файлы .c. Наш архитектор в основном состоит из модулей, которые развязаны через систему сообщений. Эти обработчики сообщений являются общедоступными и вызывают множество локальных статических рабочих функций для выполнения своей работы. Проблема возникла при попытке получить покрытие для наших случаев unit test, так как единственный способ реализовать этот частный код реализации был косвенно через общий интерфейс сообщений. С некоторыми функциями работника в коленях в стеке это оказалось кошмаром для обеспечения надлежащего покрытия.

Включение файлов .c дало нам способ добраться до винтика в машине, нам было интересно тестировать.

Ответ 5

Расширение файла не имеет значения для большинства компиляторов C, поэтому оно будет работать.

Однако, в зависимости от настроек вашего файла или проекта, включенный файл c может генерировать отдельный файл объекта. При связывании это может привести к двойным определенным символам.

Ответ 6

Вы можете использовать компилятор gcc в linux для связывания двух файлов c одним выходом. Предположим, у вас есть два c файла, один из которых - "main.c", а другой - "support.c". Таким образом, команда для соединения этих двух

gcc main.c support.c -o main.out

Эти два файла будут связаны с одним выходом main.out Для запуска вывода команда будет

./main.out

Если вы используете функцию main.c, которая объявлена ​​в файле support.c, тогда вы должны объявить ее в основном также с использованием класса extern storage.

Ответ 7

Вы можете правильно включить файлы .C или .CPP в другие исходные файлы. В зависимости от вашей среды IDE вы обычно можете предотвращать двойную привязку, просматривая свойства исходных файлов, которые хотите включить, обычно щелкая правой кнопкой мыши по ним и щелкая по свойствам, и снимите флажок/проверить компиляцию/ссылку/исключить из сборки или любой другой вариант. может быть. Или вы не можете включить файл в сам проект, поэтому среда IDE даже не знает, что она существует, и не попытается ее скомпилировать. И с make файлами вы просто просто не ставили файл в него для компиляции и компоновки.

EDIT: Извините, я дал ответ вместо ответа на другие ответы: (

Ответ 8

Язык C не запрещает такой тип #include, но результирующая единица перевода еще должна быть действительной.

Я не знаю, какую программу вы используете с .prj файлом. Если вы используете что-то вроде "make" или Visual Studio или что-то еще, просто убедитесь, что вы задали свой список файлов, которые должны быть скомпилированы без того, который не может быть скомпилирован независимо.

Ответ 9

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

Кстати, я пропустил вторую часть вопроса. Если файл C включен в другой файл и в то же время включен в проект, вы, вероятно, столкнетесь с проблемой дублирования символа, почему связывание объектов, то есть одна и та же функция будет определена дважды (если только они не статичны).

Ответ 10

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

Ответ 11

вы должны добавить заголовок, подобный этому

#include <another.c>

Примечание: оба файла должны размещаться в одном месте