防止包含 stdio.h(或其他标准 header)

Prevent inclusion of stdio.h (or other standard header)

我使用的代码库历来有意地尝试避免对 stdio.h 的依赖。它有自己的打印格式和机制,应该使用这些而不是 printf等等

但是有人经常添加一个必须引起注意并删除的依赖项。所以我试着为最简单的情况发出警报:

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

gcc 的人似乎也一直在思考如何阻止简单的错误,因为如果你这样做,会有一个有用的信息......无论你是否包含 <stdio.h>

conflicting types for built-in function 'printf'

有一种方法可以关闭此警告 (-fno-builtin)。并且有各种各样的方法可以做一些事情,比如过滤你不想在那里的东西的符号转储......

但是是否有一种非常简单的 non-warning-causing(如果您没有包括 stdio.h)的方法来提醒某人他们引入了不需要的 printf 用法?

为了防止包含 <stdio.h>,我会选择

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

您可以将 printf 重新定义为一些会导致编译或链接错误的令人讨厌的值。例如:

#define printf do_not_include_stdio_h
#include <stdio.h>

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

produces the output:

undefined reference to `do_not_include_stdio_h'

如果您希望它是一个更晦涩的名称,您可以修改宏;如果您担心某些可怜的灵魂会定义 do_not_include_stdio_h

,则可以包含无效符号

您可以在编译器标志中设置宏定义,这样您就不必手动编辑文件。例如:

gcc -Dprintf=do_not_include_stdio_h my_file.c

我根本不会碰源文件。我会修改构建脚本。更容易维护,也更容易防止人们规避限制(例如,通过更改导致编译失败的代码)。

例如,在 makefile 中,假设您有一个构建所有内容的 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 -MMmakedepend 等)并使用它来设置一种方法来搜索源文件所依赖的所有文件。如果有人下定决心,还要对您的 makefile 设置保护,这样只有您可以编辑它们。

编辑:如果您设置了生成依赖文件的工具,只需在该文件中搜索 stdio。如果任何编译单元直接或间接包含 stdio.h ,那么它将在依赖文件中列出。