Запретить включение stdio.h(или другого стандартного заголовка)

Кодовая база, с которой я работаю, исторически старалась - целенаправленно - избегать зависимостей от stdio.h, ползучего. У нее есть собственное форматирование и механизмы печати, и это то, что должно использоваться вместо printf и т.д.

Но кто-то добавляет зависимость так часто, что ее нужно замечать и вынимать. Поэтому я попытался сделать тревогу для самых простых случаев:

#if !defined(NDEBUG)
   void printf(float dont_link_with_stdio_h);
#endif

Кажется, что люди gcc думали также о том, чтобы остановить простые ошибки, потому что есть полезное сообщение, если вы это сделаете... включили ли вы <stdio.h> или нет.

конфликтующие типы для встроенной функции 'printf'

Есть способ отключить это предупреждение (-fno-builtin). И есть всевозможные подходы, которые будут делать такие вещи, как фильтр дампа символов для вещей, которые вы не хотите быть там...

Но есть ли тривиально легкое не предупреждающее предупреждение (если вы не указали stdio.h) способ предупредить кого-то, что они ввели нежелательное использование printf?

Ответ 1

Вы можете переопределить printf, чтобы быть некоторой неприятной величиной, которая вызовет ошибку компиляции или связывания. Например:

#define printf do_not_include_stdio_h
#include <stdio.h>

int main(void) {
    printf("Hello, world!\n");
    return 0;
}

выводит результат:

undefined reference to `do_not_include_stdio_h'

Вы можете выполнить макрос, если хотите, чтобы это было еще более неясное имя или включало недопустимые символы, если вы обеспокоены тем, что какая-то бедная душа определит do_not_include_stdio_h.

Вы можете установить определение макроса в флагах компилятора, чтобы вам не пришлось вручную редактировать файл (ы). Например:

gcc -Dprintf=do_not_include_stdio_h my_file.c

Ответ 2

Я бы не касался исходных файлов вообще. Я бы изменил конструкцию script. Гораздо проще в обслуживании и намного проще предотвратить людей от обхода ограничения (например, путем изменения кода, который приводит к сбою компиляции).

Например, в make файле, если у вас есть цель all, которая строит все

all:

   grep stdio *.h *.c
   if ["$?" -eq 0 ]; then
       echo "Do not use stdio.  Contact Joe for info"; exit 2;
   fi

   <other stuff to do the build here>

Вы также можете делать это по конкретным целям. Например, если у вас есть цель, которая компилирует файл .c для создания файла .o, просто проверьте файл .c перед компиляцией.

  %.o : %.c

       grep stdio $<
       if ["$?" -eq 0 ]; then
           echo "Do not use stdio.  Contact Joe for info"; exit 2;
       fi

       $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o [email protected]

Ваша единственная проблема теперь в том, что делать, если у вас есть кто-то, кто решил обойти ваше ограничение (например, #include "bypass.joe", где bypass.joe имеет #include <stdio.h>). Для этого найдите инструменты для генерации зависимостей (например, gcc -MM, makedepend и т.д.) И используйте это, чтобы настроить способ поиска всех файлов, от которых зависят исходные файлы. Если кто-то определен, также устанавливайте защиту на своих файлах make файлов, поэтому вы можете редактировать их.

EDIT: если у вас есть инструмент, настроенный для создания файла зависимостей, просто выполните поиск этого файла для stdio. Если какой-либо блок компиляции, прямо или косвенно, включает stdio.h, то он будет указан в файле зависимостей.

Ответ 3

Чтобы предотвратить включение <stdio.h>, я бы пошел с

#if !defined(NDEBUG)
#if defined(EOF)
#error Do not include stdio.h, contact Joe for more information
#endif
#endif