防止包含 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;
}
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 -MM
、makedepend
等)并使用它来设置一种方法来搜索源文件所依赖的所有文件。如果有人下定决心,还要对您的 makefile 设置保护,这样只有您可以编辑它们。
编辑:如果您设置了生成依赖文件的工具,只需在该文件中搜索 stdio
。如果任何编译单元直接或间接包含 stdio.h
,那么它将在依赖文件中列出。
我使用的代码库历来有意地尝试避免对 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;
}
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 -MM
、makedepend
等)并使用它来设置一种方法来搜索源文件所依赖的所有文件。如果有人下定决心,还要对您的 makefile 设置保护,这样只有您可以编辑它们。
编辑:如果您设置了生成依赖文件的工具,只需在该文件中搜索 stdio
。如果任何编译单元直接或间接包含 stdio.h
,那么它将在依赖文件中列出。