Ansi C - книга языков программирования K&R - включение заголовочного файла
Изучая книгу по языку программирования K&R ansi C (вторая версия), на стр. 82 приведен пример схемы файлов / папок программирования.
Что я не понимаю, пока 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 заголовочные файлы в основном предназначены для общих объявлений типов и макросов. Привычка состоит в том, что если исходный файл не нуждается в каком-либо типе или макросах, определенных в каком-либо заголовке, то ему не нужно включать этот заголовок. Возрождение этой привычки может быть тем, что здесь происходит.