Предотвратить включение 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?


person HostileFork says dont trust SE    schedule 30.12.2015    source источник
comment
Нельзя ли удалить скомпилированную версию библиотеки (.lib), чтобы она не компилировалась / компилировалась?   -  person Lee Taylor    schedule 30.12.2015
comment
@LeeTaylor Я бы предпочел не вмешиваться в среду компиляции, которая используется для других вещей, которые включают эту библиотеку (и эти вещи могут бесплатно включать stdio.h, если они хотят). Я ищу что-то менее навязчивое, чем использование метода, который я пробовал, и добавления _1 _... например. что-то, что можно сделать внутри самого источника.   -  person HostileFork says dont trust SE    schedule 30.12.2015
comment
Переопределяйте типы / структуры, а не функции.   -  person n. 1.8e9-where's-my-share m.    schedule 30.12.2015
comment
Не могли бы вы #define printf dont_include_stdio_h (или #define printf _Static_assert(0, "Do not include stdio.h"))?   -  person Cornstalks    schedule 30.12.2015
comment
@Cornstalks Я не подумал о #define, потому что боялся, что это не даст заметного сообщения ... но, превратив его в мусор как `#define printf $ dont_include_stdio_h $, он правильно все испортил таким образом, что достаточно хорошая сигнализация. Я бы воспринял это как ответ ...   -  person HostileFork says dont trust SE    schedule 30.12.2015


Ответы (3)


Вы можете переопределить 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
person Cornstalks    schedule 30.12.2015

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

Например, в 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 $@

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

РЕДАКТИРОВАТЬ: Если у вас есть инструмент, настроенный для создания файла зависимостей, просто найдите в этом файле stdio. Если какая-либо единица компиляции, прямо или косвенно, включает stdio.h, то она будет указана в файле зависимостей.

person Peter    schedule 30.12.2015
comment
Проблема с таким grepping (помимо инвазивности для make-файлов, которых я бы предпочел избегать, поскольку они генерируются еще одним процессом) заключается в том, что тогда вы беспокоитесь о том, что, если это находится в комментарии, что, если это # ​​ifdef'd out и неприменимо и т. д. Есть некоторые сторонние файлы с расширением .c, которые имеют свои собственные флаги режима отладки, поэтому должны быть списки исключений и т. д. - person HostileFork says dont trust SE; 30.12.2015
comment
Если у меня есть выбор: вторгаться в make-файл и вторгаться во все единицы компиляции (также известные как исходные файлы) в проекте, я бы выбрал первый. Даже в сложном проекте количество make-файлов редко превышает количество единиц компиляции. Существуют методы, обеспечивающие настраиваемую обработку в автоматически сгенерированных make-файлах, рекурсивное использование make и т. Д. - person Peter; 31.12.2015
comment
Разумно, и спасибо за вариант, за который проголосовали. Но для моего конкретного случая лучший выбор - не трогать make-файлы ... - person HostileFork says dont trust SE; 31.12.2015

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

#if !defined(NDEBUG)
#if defined(EOF)
#error Do not include stdio.h, contact Joe for more information
#endif
#endif
person user3386109    schedule 30.12.2015
comment
Хорошо ... хотя проблема с этим будет в том, что включение остановится только в том случае, если это включение будет после stdio.h. Хотелось бы выгрузить, если бы этот заголовок тоже был включен раньше ... - person HostileFork says dont trust SE; 30.12.2015