Является ли хорошей практикой всегда включать стандартные заголовки?

#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 зависит от file d.h , а также от file j.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.