Ansi C - книга языков программирования K&R - включение заголовочного файла

Изучая книгу по языку программирования K&R ansi C (вторая версия), на стр. 82 приведен пример схемы файлов / папок программирования.

Copyright K & R - язык программирования C - Ansi C второе издание

Что я не понимаю, пока calc.h включается в main (использование функций), getop.c (определение getop) и stack.c (определение push и pop), оно не включается в getch.c, даже если getch а также ungetch определены там.

3 ответа

Решение

Хотя это хорошая идея, чтобы включить заголовочный файл, это не обязательно, так как getch.c на самом деле не использует функцию, объявленную в calc.h, он мог бы даже обойтись, если бы он использовал только те, которые уже определены в getch.c,

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

calc.h содержит объявление getch () и ungetch (). Он включен в файлы, которые хотят использовать эти функции (и, следовательно, нуждаются в их подписи).

Вместо этого getch.c содержит определения getch () и ungetch (). Следовательно, нет необходимости включать их объявление (что неявно определено в определении).

Упущение, которое вы так удачно обнаружили, может стать источником реальной проблемы. Чтобы в полной мере использовать статическую проверку типов C в программе с несколькими переводчиками (что является почти чем-то нетривиальным), мы должны убедиться, что сайт, который определяет внешнее имя (например, функцию), а также все сайты, которые ссылаются на имя, имеют одно и то же объявление в области видимости, в идеале из одного источника: один заголовочный файл, где объявлено это имя.

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

Если вы используете компилятор GNU, вы можете защититься от этой проблемы, используя -Wmissing-prototypes, Прямо из gcc страница справочника:

       -Wmissing-прототипы (только C и Objective-C)
           Предупредить, если глобальная функция определена без предыдущего прототипа
           декларация. Это предупреждение выдается, даже если само определение
           предоставляет прототип. Цель состоит в том, чтобы обнаружить глобальные функции, которые
           не могут быть объявлены в заголовочных файлах.

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

Одна из возможных причин, по которой заголовок был забыт, заключается в том, что в примере проекта используется соглашение "один большой общий заголовок". Подход "один большой общий заголовок" позволяет программисту забыть все о заголовках. Все просто видит все остальное и #include "calc.h" это заставляет его работать - просто крошечная сноска, которую можно проглотить при амнезии.:)

Другой аспект заключается в том, что авторы потратили много времени на программирование в до-ANSI "Classic" C без объявления прототипа. В Classic C заголовочные файлы в основном предназначены для общих объявлений типов и макросов. Привычка состоит в том, что если исходный файл не нуждается в каком-либо типе или макросах, определенных в каком-либо заголовке, то ему не нужно включать этот заголовок. Возрождение этой привычки может быть тем, что здесь происходит.

Другие вопросы по тегам