Сайт о телевидении

Сайт о телевидении

» » Исходный файл c. Перевод Включая один исходный файл C в другой? От исходного кода к исполняемому модулю

Исходный файл c. Перевод Включая один исходный файл C в другой? От исходного кода к исполняемому модулю



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

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

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

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

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

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

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

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

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

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

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

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

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

#include

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

Вы можете использовать компилятор 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.

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

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

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

Отчасти это дело вкуса, поэтому, кому интересно как это делаю я, добро пожаловать под кат.

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

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

Легко заметить, что функции 1 и 2, а так же макрос 2, упомянуты в обоих файлах. И, поскольку, включение заголовочных файлов приводит к таким же результатам, как и копирование содержимого в каждый си-файл, мы можем сделать следующее:

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

  • Если нам нужно использовать функциональность, которую реализуют функции 1 и 2 где то еще, то Да
  • Если макрос 2, предназначен только для использования в файлах Unit1.c и Unit2.c, то ему не место в интерфейсном файле
Более того, действительно ли нам необходимо иметь два си-файла для реализации интерфейса, определенного в заголовочном файле? Или достаточно одного?
Ответ на этот вопрос зависит от деталей реализации интерфейсных функций и от их места реализации. Например, если сделать диаграммы более подробными, можно представить вариант, когда интерфейсные функции реализованы в разных файлах:


Такой вариант реализации приводит к высокой связности кода, низкой тестируемости и к сложности повторного использования таких модулей.
Для того, что бы не иметь таких трудностей, я всегда рассматриваю си-файл и заголовочный файл как один модуль. В котором,
  • заголовочный файл содержит только те декларации функций, типов, макросов, которые являются частью интерфейса данного модуля.
  • Си-файл, в свою очередь, должен содержать реализацию всех функций, декларированных в h- файле, а также приватные типы, макросы и функции, которые нужны для реализации интерфейса.
Таким образом, если бы мне довелось реализовывать код, которому соответствует диаграмма приведенная выше, я бы постарался, добиться следующего (окончания _с и _h в именах файлов добавлены по причине невозможности использовать точку в инструменте , которым я пользовался для создания диаграмм):


Из диаграммы видно, что на самом деле мы имеем дело с двумя независимыми модулями, у каждого из которых имеется свой интерфейс в виде заголовочного файла. Это дает возможность использовать только тот интерфейс, который действительно необходим в данном конкретном случае.Более того, эти модули могут быть протестированы независимо друг от друга.
Читатель, наверное, заметил, что макрос 2 из заголовочного файла снова вернулся в виде копии в оба си-файла. Конечно, это не очень удобно поддерживать. Но и делать данный макрос частью интерфейса не правильно.
В таких случаях, я предпочитаю делать отдельный заголовочный файл содержащий типы и макросы, необходимые нескольким си-файлам.

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

Спасибо за внимание к материалу.

support.microsoft

При изменении исходных файлов в Visual C++ и сохранить их, строки должны завершаться символов "CR/LF" [символ возврата каретки, перевода строки] сочетание. В системах UNIX строк завершаются при помощи "LF". Таким образом, при просмотре файлы, которые были изменены в группе Windows в системах UNIX может появиться множество "^ M" символы в строках. Это происходит только при использовании редактора не знает, как интерпретировать файл Windows. Visual C++ можно открывать файлы, у строк, заканчивающихся с создания UNIX LF. Если изменить этот файл и Сохраните его из Visual C++, а затем оно сохраняется в формате Windows (вы увидите CR/LF и не LF, которая ранее была в системе).

В данной статье Описывает процедуры для сохранения измененного файла, созданного на платформе Windows в формате, который может использоваться в системах UNIX.

ПРИМЕЧАНИЕ : Visual C++.NET IDE содержит функции, доступные для сохранения файла в формате UNIX. В интегрированной среде разработки сохраните файл с помощью Сохранить как... , выберите из раскрывающегося списка сохранить Сохраните с кодировкой... , и нажмите кнопку thrn Да . Выберите из раскрывающегося списка Кодировка строки UNIX (LF) , а затем нажмите кнопку ОК .

Можно использовать следующие шаги для создания консольного приложения Win32 проект, который преобразует файл, содержащий "CR/LF" для завершения строки для "LF":

  1. Чтобы создать новую с помощью консольных приложений Win32 пустой проект с именем DOS2UNIX.
  2. Из Файл меню, нажмите кнопку Новый , а затем нажмите кнопку Файлы Вкладка.
  3. Выберите Исходный файл C/C++ и введите имя нового файла DOS2UNIX.cpp.
  4. Вставьте следующий код в DOS2UNIX.cpp:

    #include #include #include using namespace std; int main(int argc, char* argv) { if(argc !=2) { cout << "Please specify: dos2unix filename" << endl; return 0; } char ch; char temp="\0"; //Open the file for reading in binarymode. ifstream fp_read(argv, ios_base::in \ / ios_base::binary); sprintf(temp, "%s.temp", argv); //Create a temporary file for writing in the binary mode. This //file will be created in the same directory as the input file. ofstream fp_write(temp, ios_base::out \ / ios_base::trunc \ / ios_base::binary); while(fp_read.eof() != true) { fp_read.get(ch); //Check for CR (carriage return) if((int)ch == 0x0D) continue; if (!fp_read.eof())fp_write.put(ch); } fp_read.close(); fp_write.close(); //Delete the existing input file. remove(argv); //Rename the temporary file to the input file. rename(temp, argv); //Delete the temporary file. remove(temp); return 0; }

  5. Из Построение меню, нажмите кнопку Создание DOS2UNIX.exe для создания EXE-файла.

Может потребоваться проверить этот exe-файл, чтобы увидеть, если он работает правильно. Для этого откройте файл в двоичном редакторе Visual C++ При выборе Открыть в группе Файл меню, выбрав DOS2UNIX.ex, Настройка Открыть как Кому Двоичный , а затем щелкнув Открыть . Например, если файл содержит "hellocrlfworld", двоичный файл данные (шестнадцатеричный) будет выглядеть так:

48 65 6 C 6 C 6F 0 D 0A 57 6F 72 6 C 64

Это эквивалентно:

Привет
Мир

В командной строке выполните команду dos2unix.exe . Далее откройте файл в двоичном редакторе Visual C++. Вы увидите, что 0x0d s, удаляются. Пока не изменить файл и сохранить его в Visual C++ 0x0d s не появится.

Это можно использовать в сочетании с Модели автоматизации Visual C++ автоматизировать весь процесс. Простой Microsoft Visual Базовый сценарий макросов могут быть написаны для вызова данного средства, но сначала необходимо это средство добавить Сервис меню выглядит следующим образом:

  1. Из Сервис меню, нажмите кнопку Настройка , а затем нажмите кнопку Сервис Вкладка.
  2. Укажите имя, например DOS2UNIX, и укажите полный путь к файлу Dos2unix.exe в Команда поле редактирования.
  3. Задайте для аргумента, $(Filename)$(FileExt).
  4. Укажите исходный каталог $(WkspDir) (укажите свой собственный путь).

Для проверки работы программы, откройте файл в Visual C++ редактор, а затем из Сервис меню запуска DOS2UNIX средство. Вы увидите, что файл, открытый в редакторе были удалены все его символы CR.

Если необходимо автоматизировать этот процесс обработать таким образом, чтобы при каждом сохранении открытого файла в редакторе Visual C++ средство DOS2UNIX.exe вызывается для удаления 0x0d s, а затем используйте следующий макрос VBScript:

"This event is fired every time the document is saved in the VC++ Editor. Sub Application_DocumentSave(theDocument) "This will call the user tool in the Tools menu. "Change the number depending upon what you have. By default you only "have 6 tools under the Tools menu, so the DOS2UNIX tool will be the 7th. ExecuteCommand "UserTool7" End Sub

Этот код VBScript будет работать только в том случае, если у вас есть файлы, открытые в Редактор Visual C++. Это единственный способ вызова exe-файл из VBScript макрос (макрос VBScript нельзя передать параметры). Можно написать в Вместо этого и это будет более гибким. Вызовите инструмент "DOS2UNIX.exe" из надстройки без необходимости добавлять его к Сервис меню.

В Visual C++ с использованием предоставленного VBScript макроса:

  1. Открыть существующий файл с расширением.dsm или создать один.
  2. Вставьте код, ранее приведенными в файл.
  3. В Visual C++ выполните следующие действия.
    1. Из Сервис меню, нажмите кнопку Настройка .
    2. Нажмите кнопку Файлы макросов и надстроек Вкладка.
    3. Нажмите кнопку Обзор загрузить файл.dsm, содержащий макрос. Один раз в файле.dsm был выбран в Обзор диалоговое окно, файл появится в Надстроек и макросов список файлов с помощью выбранного флажка рядом с ним.
    4. Нажмите кнопку Закрыть для продолжения.

Теперь, если открыть файл в редакторе Visual C++ и сохранить из файла Файл меню, вызываемого макроса и все 0x0d s будет удален из открытого файла. Так как это повлияет на любой файл, сохранить с этого момента ведется и применяются к любому проекту открыть в будущем, убедитесь, что отключить макрос из Сервис меню с помощью Настройка (снимите флажок рядом с макросом).



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

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

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

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

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

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

    Данные уровня канала и функции скрываются.

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

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

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

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

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

    Имейте один основной файл.c, который включает все дочерние файлы.c. Это может также включать код для открытого интерфейса.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Это нормально? да, он будет компилировать

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

Вы можете использовать компилятор 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.