我想知道#undef在C中的实际应用.我正在通过K&R工作,并且要接受预处理器.其中大部分是我(或多或少)理解的材料,但第90页(第二版)的内容突然出现在我面前:
名称可能未定义
#undef
,通常是为了确保例程实际上是一个函数,而不是宏:
#undef getchar
int getchar(void) { ... }
这是一种常见的做法来防御某人 - #define
一个与你的功能同名的宏吗?或者这真的是一个不会在现实中发生的样本?(EG,没有人在他的权利,错误和疯狂的头脑中应该重写getchar()
,所以它不应该出现.)有了你自己的功能名称,你觉得有必要这样做吗?如果您正在开发供其他人使用的库,这会改变吗?
如果您阅读Plauger的标准C库(1992),您将看到
允许标题提供getchar()
和getc()
类似函数的宏(具有getc()
多次评估其文件指针参数的特殊权限!).但是,即使它提供了宏,实现也必须提供执行相同工作的实际函数,主要是为了能够访问被调用的函数指针getchar()
或getc()
将其传递给其他函数.
也就是说,做:
#include#undef getchar extern int some_function(int (*)(void)); int core_function(void) { int c = some_function(getchar); return(c); }
正如所写,这core_function()
是毫无意义的,但它说明了这一点.例如,您也可以使用isxxxx()
宏执行相同的操作
.
通常,您不希望这样做 - 您通常不想删除宏定义.但是,当你需要真正的功能时,你可以掌握它.提供库的人可以模拟标准C库的功能,以达到良好的效果.
另请注意,您很少需要使用显式的原因之一#undef
是因为您可以通过编写以下方法来调用函数而不是宏:
int c = (getchar)();
因为后面的标记getchar
不是(
,它不是函数式宏的调用,所以它必须是对函数的引用.同样,上面的第一个例子,即使没有,也可以正确编译和运行#undef
.
如果使用宏覆盖实现自己的功能,则可以使用此功能,但除非另有说明,否则可能会有些混乱.
/* function.h */ … extern int function(int c); extern int other_function(int c, FILE *fp); #define function(c) other_function(c, stdout); …
/* function.c */ … /* Provide function despite macro override */ int (function)(int c) { return function(c, stdout); }
函数定义行不会调用宏,因为后面的标记function
不是(
.该return
行确实调用了宏.
宏通常用于生成大量代码.它通常是一个非常本地化的用法,并且#undef
对于特定标题末尾的任何帮助程序宏都是安全的,以避免名称冲突,因此只有实际生成的代码才会导入其他地方而用于生成代码的宏则不会.
/编辑:举个例子,我用它来为我生成结构.以下是实际项目的摘录:
#define MYLIB_MAKE_PC_PROVIDER(name) \ struct PcApi##name { \ many members … }; MYLIB_MAKE_PC_PROVIDER(SA) MYLIB_MAKE_PC_PROVIDER(SSA) MYLIB_MAKE_PC_PROVIDER(AF) #undef MYLIB_MAKE_PC_PROVIDER
由于预处理程序#define
都在一个全局命名空间中,因此很容易导致命名空间冲突,尤其是在使用第三方库时.例如,如果要创建名为的函数OpenFile
,则可能无法正确编译,因为头文件
定义OpenFile
要映射到的标记OpenFileA
或OpenFileW
(取决于是否UNICODE
已定义).正确的解决方案是#undef
OpenFile
在定义您的功能之前.