Несколько сомнений по поводу (#include) нестандартных библиотек - PullRequest
0 голосов
/ 24 мая 2019

Давайте предположим, что я пишу некоторые функции в файл, который мы будем называть foo.c. Это foo.c:

int d;

typedef int bar;

int foo(int a, int b){
 ...
}

void boo(){
 ...
}

char *test(){
 ...
}

Теперь, boo - это функция, используемая только внутри foo.c, тогда как foo(), test(), d и Bool должны быть в состоянии вызываться внутри других файлов.

Чтобы сделать это, я знаю, что должен создать файл foo.h и написать его так:

extern int d;
extern typedef int bar;
int foo(int a, int b);
char *test();

затем #include "foo.h" в файле foo.c, и всякий раз, когда я хочу использовать типы и функции, определенные в foo.c, я должен включать и foo.h, и foo.c в файл, в котором я хочу использовать Функции и типы foo.c.

Так что foo.c в итоге будет выглядеть так:

#include "foo.h"

int d;

typedef int bar;

int foo(int a, int b){
 ...
}

void boo(){
 ...
}

char *test(){
 ...
}

Вот мои вопросы.

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

Q2. Вы действительно должны поместить extern перед typedefs в файле foo.h?

Q3. Допустим, в foo.c я использую некоторые стандартные библиотеки C, такие как string.h и math.h. Где я должен включить их? Прямо в файле foo.c, в файле foo.h или в обоих? #ifndef инструкции необходимы? Если да, то как вы их правильно используете?

Q4. После записи файлов foo.c и foo.h я все готов к работе? Мол, мне не нужно их компилировать или что-то еще, верно? Я могу просто #include их где угодно, просто так?

В5. Где-то еще я читал, что если я хочу использовать пользовательскую библиотеку, мне нужно выполнить следующие шаги:

  • определить интерфейс (foo.h)
  • запись foo.c # включая foo.h
  • создание объектного файла, подобного этому gcc -o foo.o -c foo.c
  • включая foo.h в программе, в которой я хочу использовать foo.c функции
  • связывание объектного файла следующим образом gcc my_proj.c foo.o

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

Спасибо за ваше время и извините, если это немного долго

Ответы [ 2 ]

3 голосов
/ 24 мая 2019

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

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

Q2.Вам действительно нужно помещать внешний файл перед typedefs в файле foo.h?

Нет, typedefs не нужно extern.

Q3.Допустим, в foo.c я использую некоторые стандартные библиотеки C, такие как string.h и math.h.Где я должен включить их?Прямо в файле foo.c, в файле foo.h или в обоих?Нужны ли инструкции #ifndef?Если да, то как вы их правильно используете?

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

Q4.После написания файлов foo.c и foo.h я все готов к работе?Мол, мне не нужно их компилировать или что-то еще, верно?Я могу просто # включить их туда, где мне нужно, просто так?

Вы можете скомпилировать их, чтобы получить что-то вызываемое.Если вы не скомпилируете свою программу, вы не сможете ее использовать.Или я вас не так понимаю?

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

[snip]

Действительно, это один из способовидти.Шаги 1, 2 и 4 не могут быть опущены по очевидным причинам.Но вы можете выполнить шаги 3 и 5 вместе, выполнив

gcc my_proj.c foo.c

. Это скомпилирует данные файлы и затем соединит их вместе в одном вызове.

Почему мне нужно только включитьfoo.h в файле, в котором я хочу использовать функции foo.c?

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

Что такое объектный файл?

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

Другими словами: объектный файл - это скомпилированная версия исходного файла.Он «предоставляет» идентификаторы, необходимые для других объектных файлов, и «требует» другие идентификаторы, предоставленные другими файлами.Связывание их вместе означает, что требуемый и предоставленный объекты связаны соответствующим образом, чтобы программа могла работать.

Пример: у вас есть файл foo.c, который определяет функции foo и test.Затем у вас есть main.c, который использует эти функции и предоставляет функцию main.В конце они связаны друг с другом и объединяются с кодом запуска, который необходим для запуска программы и который вызывает main().Точки в main(), где foo() и test() вызываются соответственно, помечены особым образом, чтобы компоновщик мог поместить туда фактический адрес вызова.

1 голос
/ 24 мая 2019

Q1.Вы действительно так делаете?

Нет

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

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

Разве я не могу просто напрямую определить функции внутри файла foo.c, вообще не используя файл foo.h?

Обычно нет.Это должны делать только static inline функции.

Q2.Вы действительно должны поместить extern перед typedefs в файле foo.h?

No: typedef int foobar_t;

Q3.Допустим, в foo.c я использую некоторые стандартные библиотеки C, такие как string.h и math.h.Где их включить?

В файле, который нуждается в них (foo.c).Включите в каждый файл только те заголовки, которые ему нужны.Больше не надо;не менее.

Непосредственно в файле foo.c, в файле foo.h или в обоих файлах?

foo.c

Нужны ли #ifndefinstructions?Если да, то как вы их правильно используете?

Да:

// foo.h
#ifndef FOO_H
#define FOO_H

Here go all the contents of foo.h

#endif     /* foo.h */

Q4.После написания файлов foo.c и foo.h я все готов к работе?Мол, мне не нужно их компилировать или что-то еще, верно?Я могу просто # включить их куда угодно, просто так?

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

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

определить интерфейс (foo.h)

write foo.c #включив в foo.h

создание объектного файла, подобного этому gcc -o foo.o -c foo.c

, включая foo.h в программе, в которой я хочу использовать foo.cфункции

связывание объектного файла следующим образом: gcc my_proj.c foo.o

Эти шаги действительно необходимы?

Да

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

Подробнее о компиляции и компоновке.

Чтоточно объектный файл?

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

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