2013-08-25 2 views
8

Итак, я следую в Head First C, и мы находимся в главе, где мы учимся собирать несколько файлов вместе. Один из них - encrypt.c.Почему мне нужно включить файл заголовка .h в .c файл с тем же именем?

#include "encrypt.h" 


void encrypt(char *message) 
{ 
    char c; 
    while (*message) { 
    *message = *message^31; 
    message++; 
    } 
} 

encrypt.h файл повторяет первую строку с точкой с запятой в конце, так зачем мне это нужно? Я понимаю, почему мне нужны файлы заголовков, чтобы исправить проблему использования функции до ее определения, поэтому я мог понять #include в файле, который использует encrypt.c, но зачем мне это нужно в encrypt.c? Это лишь одна из причин «из-за»?

+0

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

+3

Не относится к этому конкретному примеру, но файлы заголовков также часто определяют 'typedef' и 'struct' и всевозможные вещи, которые могут использоваться функции, объявленные в этом заголовке. –

+0

У меня есть и другие. У этой книги есть недостатки, но все они делают. – punstress

ответ

16

Если содержимое encrypt.c показано полностью, то вы не должны заголовок. Но это все же хорошая идея включить его, потому что:

  1. Если одна из функций в файле использует другую, то порядок определения имеет значение, поскольку вызывающий должен быть определен перед вызывающим. Также возможно иметь две функции A и B, где каждый вызывает другой, и в этом случае вы не можете получить код для компиляции без хотя бы одного прямого объявления. Включение заголовка с форвардными объявлениями решает эти проблемы.
  2. Использование заголовка точно так же, как ваш код клиента, является хорошим способом, чтобы компилятор указывал на несоответствия между сигнатурами в форвардных декларациях и определениями фактических функций. Если это не обнаружено, такая проблема может привести к «интересному» поведению во время выполнения и множеству притягивания волос.
+1

Мне нравится ваш второй пункт. Книга подняла ваш первый пункт функций, которые взаимно называют друг друга, поэтому пинг вызывает ping и pong-вызовы ping, и я понимаю, как заголовок разрешит это, но я подумал, что здесь у нас есть только одна функция, это просто получить я по привычке? – punstress

+1

@punstress: По существу это так. И это хорошая привычка. ;-) – Jon

+0

@Jon По сути, это хорошая практика всегда отделять интерфейс от реализации, не так ли? – NlightNFotis

6

Вы правы, если все это encrypt.h заявляет, что его не нужно включать в файл .c.

Вы в основном делаете это для согласованности.

+0

Я думал, что это что-то вроде этого, спасибо. – punstress

4

Представьте себе, что вы меняете encrypt.c к void encrypt(char *message, int i) { }

Если вы не включаете encrypt.h вы не заметите, что другие файлы в вашем приложении не были обновлены, чтобы передать новый параметр. Если вы одновременно обновите encrypt.h и encrypt.c, компилятор может проверить вас.

+0

Было просто перечитывать это с прошлого года, и мне нравится ваша мысль. Спасибо. – punstress

1

Это хороший стиль. Иногда C-файл с реализацией функции и C-файлом с использованием функций использует общие объявления - типы/структуры, объявляет объявления в H-файле. Для примера.

[enc.h] 
typedef enum {S,F} Res; 
EN encode(); 

[enc.c] 
#include "enc.h" 
Res encode() { ... } 

[other.c] 
Res res; 
res = encode(); 
0

Затем вы включаете заголовок в другой * .c-файл, который компилятор знает таким образом, что в другом месте это определение функции.

Это IST как:

#include <stdio.h> 

int main (void) 
{ 
    afun(); 
    return 0; 
} 

void afun (void) 
{ 
    printf("hello\n"); 
} 

Теперь компилятор не знает, что делать с afun() в главной функции. Потому что он не был определен. Таким образом, это приведет к ошибке компилятора.

Таким образом, вы добавить объявление в начале или bevore первого использования:

#include <stdio.h> 

void afun(void); 

int main (void) 
{ 
    afun(); 
    return 0; 
} 

void afun (void) 
{ 
    printf("hello\n"); 
} 

Знать компилятор знает deklaration из afun и надеется anythere еще функция определена. С заголовочными файлами можно использовать предварительно скомпилированный c-код. Единственное, что требуется компилятору, это деблокирование функции.

+1

OP сказал: «Я понимаю, почему мне нужны файлы заголовков, чтобы исправить проблему использования функции до ее определения» прямо в ее начальном сообщении ... –

+0

Да, я бы показал: С заголовочными файлами можно использовать предварительно скомпилированный c -код. – Alex44

Смежные вопросы