#c #header #conventions
#c #заголовок #соглашения
Вопрос:
Я прочитал ответ на этом сайте, объясняющий, почему не всегда следует включать все (защищенные от включения) файлы заголовков — замедляет время компиляции, загрязняет глобальное пространство имен и т.д.
Но я хотел бы спросить конкретно — всегда ли включение стандартных заголовков, таких как <stdlib.h>
и <stdio.h>
, считается хорошей или плохой практикой?
Почему я не должен поддерживать stdheaders.h
файл с #include
s для всех стандартных заголовков и просто включать его везде? Я думаю, это могло бы избавить меня от ошибок, когда я использую функцию, для которой я забыл включить стандартный заголовок.
В частности, я хотел бы знать, что считается стандартной практикой в разработке на C. Спасибо
Комментарии:
1. Включайте только то, что вы используете.
2. Почему было бы хорошей практикой включать их, если вы их не используете? Вы также всегда используете
int i,j,k;
во всех функциях на всякий случай?3. Включение большего количества заголовков, чем вам нужно, увеличивает время компиляции. Включите каждый заголовок, необходимый для того, что вы используете, и ничего более.
4. Если вы используете функцию, для которой вы не включили заголовок, и ваш компилятор не предоставляет диагностику, вам нужны более строгие флаги, а не заголовок megazord.
5. Но тогда необходимость возвращаться назад, идентифицировать, редактировать и перестраивать, когда вы пропускаете один, значительно увеличивает время программиста, скажем, на 20 секунд за раз, если это не тривиально, и потенциально 1 новая зависимость заголовка на каждые 50 строк кода может составлять до часа в неделю, что потенциально составляет 50 долларов в неделю на разработчика. Также я упоминал ранее о проблеме, из-за которой мы все полагаемся на случайные системные включения, которые будут прерываться с новыми выпусками библиотеки. Один файл заголовка monolith для системы включает, второй для вашего API, ориентированного на клиента, и третий для основных внутренних компонентов означает, что проблема уменьшается.
Ответ №1:
Рекомендуется для каждого исходного файла, будь то файл .c или .h, включать только те заголовки, которые ему необходимы. Это не только сокращает время компиляции, но и служит для документирования функциональности файла.
Вот несколько примеров:
f1.c:
#include <stdio.h>
void print_int(int i)
{
printf("i=%dn", i);
}
f2.c:
#include <stdlib.h>
void *safe_malloc(size_t size)
{
void *p = malloc(size);
if (!p) exit(1);
return p;
}
f3.c:
int sum(int a, int b)
{
return a b;
}
Файл f1.c включает только stdio.h, потому что он выполняет ввод-вывод, но никаких других функций. Аналогично, f2.c включает stdlib.h только потому, что он использует определенные там функции, но не использует никаких функций ввода-вывода, а f3.c не включает никаких заголовков, потому что они ему не нужны.
Если вы считаете, что включили ненужные файлы, закомментируйте их и скомпилируйте со включенными всеми предупреждениями, чтобы увидеть, какие из них объявляют функции или переменные, которые вам нужны.
Комментарии:
1. Спасибо за ваш вклад. Если позволите, последующий вопрос: предположим, file
a.c
зависит от filed.h
, а также от filej.h
. Файлj.h
зависит также отd.h
. Это означает, чтоa.c
не обязательно включатьd.h
напрямую — это уже включено черезj.h
. Когда я изначально начинаю писатьa.c
, должно ли это все еще явно включатьd.h
?2. @AvivCohn Если a.c имеет прямую зависимость от d.h, он должен включать это. Таким образом, все не будет неожиданно прервано, если j.h удалит зависимость от d.h.