Почему заголовочный файл добавляется в исходный код, где функция уже определена? - PullRequest
0 голосов
/ 31 января 2019

Например, если у меня есть следующие три файла, написанные на C:

hello.h

void hello (const char * name);

hello.c

#include "hello.h"
int
main (void)
{
hello ("world");
return 0;
}

hello_fn.c

#include <stdio.h>
#include "hello.h"
void
hello (const char * name)
{
printf ("Hello, %s!\n", name);
}

Я знаю, что добавление строки #include "hello.h" в hello.c сообщает компилятору, чтоопределение hello (const char * name) будет предоставлено во время внешнего файла (отдельная компиляция), , но теперь мой вопрос, почему он добавляется в файл hello_fn.c, когда hello_fn.c содержит его само определение hello (const char * name)Я имею в виду, он не будет поставляться извне?

Спасибо

1 Ответ

0 голосов
/ 31 января 2019

Это на самом деле хорошая практика, поскольку компилятор может проверить ваше объявление (в заголовке) на соответствие вашему определению (в hello_fn.c).

Без этого невозможно обеспечить их соответствие.Вы можете довольно легко поместить:

void hello (int notCorrect) { ... }

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


Например, рассмотрим файлы:

hello.c:
    #include <stdio.h>
    #include "hello.h"
    int main(void) { hello(42); }
hello_fn.c:
    #include <stdio.h>
    //#include "hello.h"
    void hello(char *x) { puts(x); }
hello.h:
    int hello(int x);

Это прекрасно компилируется, поскольку каждый исходный файл C внутренне согласован в том, что он утверждает.Пара hello.c/hello.h считает, что hello принимает int, а hello_fn.c думает, что она принимает строку C.

Я получаю дамп ядра (1) во время работы, потому чтозначение 42 не является допустимым строковым адресом.Когда я раскомментирую строку include в hello_fn.c, компилятор жалуется (справедливо), что мое объявление и определение не совпадают (потому что пара hello_fn.c/hello.h теперь несовместима).


Кроме того, может быть другой материал в заголовке (но не в вашем примере), который существует только в заголовке.Обычно это объявления, которые являются общими для вызывающего и вызываемого абонентов, такие как типы, extern items, #define items и т. Д.Не имеет смысла объявлять их отдельно в заголовке и исходном файле.


(1) Фактические результаты могут отличаться, посколькуэто неопределенное поведение.

...