我们都熟悉像C这样的语言中的宏工作。在某些情况下,由于意外捕获标识符,宏扩展会导致不良结果。
例如:
// C program to illustrate a situation known as
// accidental capture of identifiers - an
// undesirable result caused by unhygienic macros
#define INCI(i) do { int x = 0; ++i; } while(0)
int main(void)
{
int x = 4, y = 8;
// macro called first time
INCI(x);
// macro called second time
INCI(y);
printf("x = %d, b = %d\n", x, y);
return 0;
}
该代码实际上等效于:
// C program to illustrate unhygenic macros
// with Macro definition substituted in source code.
int main(void)
{
int x = 4, y = 8;
//macro called first time
do { int x = 0; ++x; } while(0);
//macro called second time
do { int x = 0; ++y; } while(0);
printf("x = %d, b = %d\n", x, y);
return 0;
}
输出:
x = 4, y = 9
在主函数范围内声明的变量a被宏定义中的变量a遮盖,因此a = 4永远不会更新(称为意外捕获)。
卫生宏
卫生宏是保证扩展不会引起标识符意外捕获的宏。卫生宏不使用可能会干扰正在扩展的代码的变量名。
只需更改宏定义中变量的名称,就可以避免上述代码中的情况,这将产生不同的输出。
// C program to illustrate
// Hygienic macros using
// identifier names such that
// they do not cause
// the accidental capture of identifiers
#define INCI(i) do { int m = 0; ++i; } while(0)
int main(void)
{
int x = 4, y = 8;
// macro called first time
INCI(x);
// macro called second time
INCI(y);
printf("x = %d, y = %d\n", x, y);
return 0;
}
输出:
x = 5, y = 9
想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。