Windows. Железо. Интернет. Безопасность. Программы
  • Главная
  • Windows 7
  • Перевод Включая один исходный файл C в другой? Что должно быть в с-файле, а что должно быть в h-файле? От исходного кода к исполняемому модулю

Перевод Включая один исходный файл C в другой? Что должно быть в с-файле, а что должно быть в h-файле? От исходного кода к исполняемому модулю

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

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

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

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

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

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

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


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


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

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

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

Исходные файлы

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

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

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

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

В нижеследующем примере исходная программа состоит из двух исходных файлов. Функции main и max представлены в отдельных файлах. Функция main использует функцию max в процессе своего выполнения.

/* исходный файл 1 - функция main */

extern int max (int, int); /* объявление функции */

main () /* определение функции */

int w = ONE, x = TWO, у = THREE;

/* исходный файл 2 - функция max */

int max (a, b) /* определение функции */

В первом исходном файле функция max объявлена, но не определена. Такое объявление функции называется предварительным; оно позволяет компилятору контролировать обращение к функции до того, как она определена. Определение функции main содержит вызовы функции max .

Строки, начинающиеся с символа #, являются директивами препроцессора. Директивы указывают препроцессору на необходимость замены в первом исходном файле идентификаторов ONE, TWO, THREE на соответствующие значения. Область действия директив не распространяется на второй исходный файл.

Программирование Козлова Ирина Сергеевна

27. Исходные файлы С++

27. Исходные файлы С++

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

extern double sqrt(double); extern instream cin;

Самый простой способ обеспечить согласованность исходных файлов – помещение таких же описаний в отдельные файлы, которые называются заголовочными (или хэдер) файлами, после чего включить, т. е. скопировать, эти заголовочные файлы во все файлы, где необходимы эти описания. К примеру, если описание sqrt располагается в заголовочном файле для стандартных математических функций math.h и необходимо извлечь квадратный корень из 4, следует применить программу:

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

В команде включения include имя файла, которое располагается в угловых скобках, например, относится к файлу с таким именем в стандартном каталоге (обычно это /usr/include/CC); на файлы, хранящиеся в других местах, ссылаются, применяя имена, расположенные в двойных кавычках. Например:

#include «math1.h» #include «/usr/bs/math2.h»

включит math1.h из текущего пользовательского каталога, а math2.h из каталога /usr/bs.

Покажем, как мы могли бы определить тип потока вывода ostream. Для упрощения задачи предположим, что для буферизации определен тип streambuf. Тип streambuf определен в том месте, где также располагается и настоящее определение ostream. Значение типа, определяемого пользователем, специфицирует данные, которые нужны для представления объекта этого типа, и большое число операций для работы с этими объектами. Определение состоит из двух частей: закрытой (private) части, в которой находится информация, используемая только его разработчиком, и открытой (public) части, являющейся интерфейсом типа с пользователем.

Из книги Программы и файлы Windows автора Климов А

DBX-файлы В файлах с расширением DBX хранятся записи программы Outlook Express. В этих файлах, называемых Банком сообщений, находятся письма, сообщения новостных групп и т.п. При желании, можно скопировать эти файлы на носитель информации для переноса данных в другой компьютер.

Из книги Программирование автора Козлова Ирина Сергеевна

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

Из книги Win2K FAQ (v. 6.0) автора Шашков Алексей

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

Из книги Microsoft Visual C++ и MFC. Программирование для Windows 95 и Windows NT автора Фролов Александр Вячеславович

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

Из книги UNIX: взаимодействие процессов автора Стивенс Уильям Ричард

Файлы По многочисленным просьбам открываем раздел с полезными файлами для W2k. Раздел состоит из двух частей, первая официальные патчи от Microsoft (не все, а только те, что кажутся нам наиболее важными), и вторая часть, куда войдут все файлы упоминавшиеся в FAQ, просто утилитки,

Из книги Язык программирования Си для персонального компьютера автора Бочков C. О.

Из книги КОМПАС-3D для студентов и школьников. Черчение, информатика, геометрия автора Большаков Владимир

Из книги Недокументированные и малоизвестные возможности Windows XP автора Клименко Роман Александрович

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

Из книги Программирование для Linux. Профессиональный подход автора Митчелл Марк

Приложение 2 Исходные данные для твердотельного моделирования

Из книги UNIX: разработка сетевых приложений автора Стивенс Уильям Ричард

Приложение 3 Исходные данные для моделирования семейств

Из книги Wiki-правительство [Как технологии могут сделать власть лучше, демократию – сильнее, а граждан – влиятельнее] автора Новек Бет

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

Из книги UNIX - универсальная среда программирования автора Пайк Роб

1.5.4. Исходные тексты Linux - система с открытым кодом, не так ли? Верховным судьей, определяющим, как работает система, является исходный код самой системы. К нашему счастью, он доступен бесплатно. В имеющийся дистрибутив Linux могут входить исходные тексты всей системы и всех

Из книги автора

А.3.5. Исходные тексты программы-калькулятора В листинге А.3 показан текст программы, вычисляющей значения постфиксных выражений.Листинг А.3. (calculator.c) Основная часть программы-калькулятора/* Вычисления в унарном формате. *//* На вход программы подаются однострочные

Из книги автора

Приложение Г Различные исходные коды Г.1. Заголовочный файл unp.h Почти каждая программа в этой книге начинается с подключения заголовочного файла unp.h, показанного в листинге Г.1. Этот файл подключает все стандартные системные заголовочные файлы, необходимые для работы

Из книги автора

Из книги автора

Приложение 3 Исходные тексты калькулятора hoc These files contain all the code from "The Unix Programming Environment", by Brian Kernighan and Rob Pike (Prentice Hall, 1984, ISBN 0-13-937681-X). A separate hoc6 distribution contains any fixes that we have applied to that; the version in this file is from the book.Copyright © Lucent Technologies, 1997. All Rights ReservedPermission to use, copy, modify, and distribute this software and its documentation for

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 будет удален из открытого файла. Так как это повлияет на любой файл, сохранить с этого момента ведется и применяются к любому проекту открыть в будущем, убедитесь, что отключить макрос из Сервис меню с помощью Настройка (снимите флажок рядом с макросом).

Лучшие статьи по теме