изходен файл c. Онлайн Включване на един C изходен файл в друг? Какво може да има в заглавния файл

изходен файл c.  Онлайн Включване на един C изходен файл в друг?  Какво може да има в заглавния файл
изходен файл c. Онлайн Включване на един C изходен файл в друг? Какво може да има в заглавния файл

Наскоро ми беше зададен подобен въпрос от колега, който започва да програмира на езика C. И реших, че това е добра възможност да споделя разбирането си този проблем. Защото дори опитни програмисти не винаги имат подобни гледни точки по този въпрос.

Това отчасти е въпрос на вкус, така че ако някой се интересува как го правя, добре дошъл под кат.

Въпреки че „цялата истина“ за h-файловете се съдържа в съответния раздел на описанието на препроцесора gcc, ще си позволя някои обяснения и илюстрации.

И така, буквално, заглавният файл (h-файл) е файл, съдържащ C декларации и макродефиниции, предназначени да бъдат използвани в множество изходни файлове (c-файлове). Нека илюстрираме това.

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

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

  • Ако трябва да използваме функционалността, която функции 1 и 2 изпълняват някъде другаде, тогава Да
  • Ако макрос 2 е предназначен само за използване във файлове Unit1.c и Unit2.c, тогава той няма място в интерфейсния файл
Освен това, наистина ли трябва да имаме два C файла, за да реализираме интерфейса, дефиниран в заглавния файл? Или едно е достатъчно?
Отговорът на този въпрос зависи от детайлите на изпълнението на функциите на интерфейса и къде са внедрени. Например, ако направите диаграмите по-подробни, можете да си представите случая, когато функциите на интерфейса се изпълняват в различни файлове:


Тази опция за внедряване води до висока кохезия на кода, ниска възможност за тестване и трудности при повторното използване на такива модули.
За да нямам такива затруднения, винаги третирам C-файла и заглавния файл като едно цяло. В който,
  • заглавният файл съдържа само тези декларации на функции, типове, макроси, които са част от интерфейса на този модул.
  • C-файлът от своя страна трябва да съдържа изпълнението на всички функции, декларирани в h-файла, както и частни типове, макроси и функции, които са необходими за реализиране на интерфейса.
По този начин, ако се случи да внедря кода, който съответства на диаграмата по-горе, ще се опитам да постигна следното (окончанията _c и _h в имената на файловете бяха добавени поради невъзможността да се използва точка в инструмента, който използвах за създаване на диаграми):


От диаграмата се вижда, че всъщност имаме работа с два независими модула, всеки от които има собствен интерфейс под формата на заглавен файл. Това дава възможност да се използва само интерфейсът, който наистина е необходим в конкретния случай, освен това тези модули могат да бъдат тествани независимо един от друг.
Читателят може да е забелязал, че макрос 2 от заглавния файл се връща като копие и в двата C-файла. Разбира се, това не е много удобно за поддръжка. Но да се направи този макрос част от интерфейса не е правилно.
В такива случаи предпочитам да направя отделен заглавен файл, съдържащ типовете и макросите, необходими за няколко C файла.

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

Благодаря за вниманието към материала.



В зависимост от вашата среда за изграждане (няма да уточнявате) може да откриете, че работи точно както искате.

Въпреки това има много среди (както IDE, така и много ръчно изработени Makefiles), които очакват *.c да бъде компилиран - ако това се случи, е вероятно да попаднете на грешки на свързване поради дублиране на символи.

Като общо правило тази практика трябва да се избягва.

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

Включването на C файл в друг файл е законно, но не е препоръчително, освен ако не знаете точно защо го правите и какво се опитвате да постигнете.
Почти съм сигурен, че ако публикувате тук причината, поради която въпросът ви е докладван на общността, ще намерите друг подходящ начин да постигнете целта си (обърнете внимание на „почти“, тъй като е възможно това да е решение, предвид контекста ).

Между другото, пропуснах втората част от въпроса. Ако C файлът е включен в друг файл и е включен в проекта едновременно, вероятно ще се сблъскате с проблема с дублиране на символи, защо обвързване на обекти, т.е. една и съща функция ще бъде дефинирана два пъти (освен ако не са статични).

Езикът C не забранява такъв тип #include, но получената единица за превод все още трябва да бъде валиден C.

Не знам каква програма използвате с .prj файла. Ако използвате нещо като "make" или Visual Studio или каквото и да е, просто се уверете, че сте го задали на списък с файлове, които трябва да бъдат компилирани, без такъв, който не може да бъде компилиран независимо.

Можете да използвате gcc компилатора на linux, за да свържете два файла към един изход. Да предположим, че имате два c файла, единият е "main.c", а другият е "support.c". Така че командата за свързване на тези две

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

Тези два файла ще бъдат свързани към един main.out изход. За да стартирате изхода, командата ще бъде

./главен.изход

Ако използвате main.c функция, която е декларирана във файла support.c, тогава трябва да я декларирате в main, като използвате и extern клас за съхранение.

Използвана правилно, това може да бъде полезна техника.

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

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

С C можете да загубите много, като направите това. Почти всички инструменти осигуряват прилични оптимизации за единична компилационна единица, но са много песимистични за всичко, декларирано като extern.

Ако поставите всичко в един модул C източник, получавате -

    Подобрения в производителността и размера на кода - в много случаи извикванията на функции ще бъдат вградени. Дори и без вграждане, компилаторът има място за генериране на по-ефективен код.

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

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

    По-бързо компилиране и свързване.

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

Трябва обаче да наложите някои конвенции, за да се справите с това. До известна степен това ще зависи от вашата верига от инструменти, но някои общи указания са

    Поставете публичния интерфейс в отделен заглавен файл - така или иначе трябва да го направите.

    Имате един основен .c файл, който включва всички дъщерни .c файлове. Може също да включва код за публичния интерфейс.

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

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

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

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

Разширението на файла няма значение за повечето C компилатори, така че ще работи.

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

трябва да добавите заглавка като тази

#включи

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

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

РЕДАКТИРАНЕ: Съжалявам, че дадох отговор, вместо да отговоря на други отговори :(



гласувайте онлайн (8)

Включването на C файл в друг файл е законно, но не е препоръчително, освен ако не знаете точно защо го правите и какво се опитвате да постигнете.
Почти съм сигурен, че ако публикувате тук причината, поради която въпросът ви е докладван на общността, ще намерите друг подходящ начин да постигнете целта си (обърнете внимание на „почти“, тъй като е възможно това да е решение, предвид контекста ).

Между другото, пропуснах втората част от въпроса. Ако C файлът е включен в друг файл и е включен в проекта едновременно, вероятно ще се сблъскате с проблема с дублиране на символи, защо обвързване на обекти, т.е. една и съща функция ще бъде дефинирана два пъти (освен ако не са статични).

Разширението на файла няма значение за повечето C компилатори, така че ще работи.

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

В зависимост от вашата среда за изграждане (няма да уточнявате) може да откриете, че работи точно както искате.

Въпреки това има много среди (както IDE, така и много ръчно изработени Makefiles), които очакват *.c да бъде компилиран - ако това се случи, е вероятно да попаднете на грешки на свързване поради дублиране на символи.

Като общо правило тази практика трябва да се избягва.

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

Можете да използвате gcc компилатора на linux, за да свържете два файла към един изход. Да предположим, че имате два c файла, единият е "main.c", а другият е "support.c". Така че командата за свързване на тези две

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

Тези два файла ще бъдат свързани към един main.out изход. За да стартирате изхода, командата ще бъде

./главен.изход

Ако използвате main.c функция, която е декларирана във файла support.c, тогава трябва да я декларирате в main, като използвате и extern клас за съхранение.

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

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

Езикът C не забранява такъв тип #include, но получената единица за превод все още трябва да бъде валиден C.

Не знам каква програма използвате с .prj файла. Ако използвате нещо като "make" или Visual Studio или каквото и да е, просто се уверете, че сте го задали на списък с файлове, които трябва да бъдат компилирани, без такъв, който не може да бъде компилиран независимо.

Използвана правилно, това може да бъде полезна техника.

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

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

С C можете да загубите много, като направите това. Почти всички инструменти осигуряват прилични оптимизации за единична компилационна единица, но са много песимистични за всичко, декларирано като extern.

Ако поставите всичко в един модул C източник, получавате -

    Подобрения в производителността и размера на кода - в много случаи извикванията на функции ще бъдат вградени. Дори и без вграждане, компилаторът има място за генериране на по-ефективен код.

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

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

    По-бързо компилиране и свързване.

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

Трябва обаче да наложите някои конвенции, за да се справите с това. До известна степен това ще зависи от вашата верига от инструменти, но някои общи указания са

    Поставете публичния интерфейс в отделен заглавен файл - така или иначе трябва да го направите.

    Имате един основен .c файл, който включва всички дъщерни .c файлове. Може също да включва код за публичния интерфейс.

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

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

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

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

Това е добре? да, ще се компилира

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

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

27. C++ изходни файлове

27. C++ изходни файлове

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

extern double sqrt(double); външен instream cin;

Най-лесният начин да поддържате изходните файлове последователни е да поставите еднакви описания отделни файлове, които се наричат ​​заглавни (или заглавни) файлове, и след това включват, т.е. копират тези заглавни файлове във всички файлове, където са необходими тези описания. Например, ако дефиницията на sqrt се намира в заглавния файл за стандартните математически функции math.h и трябва да извлечете корен квадратен от 4, трябва да използвате програмата:

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

В команда за включване името на файла, оградено в ъглови скоби, например, се отнася до файла с това име в стандартната директория (обикновено /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++ Програмата на C++ най-често включва голям брой изходни файлове, всеки от които съдържа описания на типове, функции, променливи и константи. За да може едно име да се използва в различни изходни файлове за препращане към конкретен обект, то

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

Файлове По масово искане отворете секцията с полезни файловеза w2k. Разделът се състои от две части, първата е официални пачове от Microsoft (не всички, но само тези, които ни се струват най-важни), а втората част, която ще включва всички файлове, споменати в ЧЗВ, само помощни програми,

От книгата Езикът за програмиране C за персонален компютър автор Бочков С. О.

От книгата KOMPAS-3D за студенти и ученици. Рисуване, информатика, геометрия автор Болшаков Владимир

От книгата Недокументирано и малко известно Функции на Windows XP автор Клименко Роман Александрович

Изходни файлове Текстът на C програма може да бъде разделен на няколко изходни файла. Изходният файл е текстов файл, който съдържа или цялата програма, или част от нея. Когато компилирате изходна програма, всеки от нейните съставни изходни файлове

От книгата Програмиране за Linux. Професионален подход автор Мичъл Марк

Приложение 2 Входни данни за солидно моделиране

От книга за UNIX: Разработка мрежови приложения автор Стивънс Уилям Ричард

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

От Wiki-Government [Как технологиите могат да направят властта по-добра, демокрацията по-силна и гражданите по-мощни] автор Новек Бет

CPL файлове От предишните няколко параграфа научихте почти всички теоретични изчисления, които са необходими за работа с програмата rundll32.exe. Сега ще изброим възможностите, които тази програмаможе да предостави на потребителя. Да започнем с описание

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

1.5.4. Източникът на Linux е система с отворен код, нали? Крайният съдия за това как работи една система е изходният код на самата система. За наш късмет е достъпен безплатно. На разположение Linux дистрибуцияможе да включва изходния код на цялата система и всичко останало

От книгата на автора

А.3.5. Изходните текстове на програмата калкулатор Листинг A.3 показва текста на програмата, която изчислява стойностите на постфиксните изрази Листинг A.3. (calculator.c) Основната част на калкулатора/* Изчисления в унарен формат. *//* Една линия

От книгата на автора

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

От книгата на автора

От книгата на автора

Приложение 3 Източници на Hoc калкулатор Тези файлове съдържат целия код от "Средата за програмиране на Unix", от Brian Kernighan и Rob Pike (Prentice Hall, 1984, ISBN 0-13-937681-X). Отделно разпространение на hoc6 съдържа всички корекции, които сме приложили към това; версията в този файл е от книгата. Авторско право © Lucent Technologies, 1997. Всички права запазени Разрешение за използване, копиране, модифициране и разпространение на този софтуер и неговата документация за