我想使用预处理器注释一行:
#define open /##*
#define close */
main()
{
open commented line close
}
当我这样做时,$gcc -E filename.c
我期望
/* commented line */
但我得到了
/ * commented line */
以便编译器显示错误
为什么它给了一个不需要的空间?
我想使用预处理器注释一行:
#define open /##*
#define close */
main()
{
open commented line close
}
当我这样做时,$gcc -E filename.c
我期望
/* commented line */
但我得到了
/ * commented line */
以便编译器显示错误
为什么它给了一个不需要的空间?
来自 GNU C 预处理器文档:
但是,不能将不一起形成有效令牌的两个令牌粘贴在一起。例如,您不能以任一顺序将 x 与 + 连接。如果您尝试,预处理器会发出警告并发出两个令牌。是否在标记之间放置空白是未定义的。在复杂的宏中发现“##”的不必要使用是很常见的。如果您收到此警告,很可能您可以简单地删除“##”。
在这种情况下,“*”和“/”不会形成有效的 C 或 C++ 标记。所以它们被发射出来,它们之间有一个空间。
(除此之外:即使您设法在 C 预处理器的输出中插入“注释”,您也可能会遇到 C 编译错误。那里不应该有任何注释。)
错误是因为/*
不是有效的令牌。
正如CPP 文档所解释的:
不能一起形成有效标记的两个标记不能粘贴在一起。例如,您不能以任一顺序连接
x
with+
。
您可以通过粘贴其他无意义的东西(例如/##+
或+##-
.
关于空间,它是故意插入的,以避免创建评论并弄乱其余部分。从GCC 源代码:
/* Avoid comment headers, since they are still processed in stage 3.
It is simpler to insert a space here, rather than modifying the
lexer to ignore comments in some circumstances. Simply returning
false doesn't work, since we want to clear the PASTE_LEFT flag. */
if ((*plhs)->type == CPP_DIV && rhs->type != CPP_EQ)
*end++ = ' ';
预处理器以 C 编译器可以理解的形式运行并生成代码。它只处理你的代码一次,所以即使你可以/*
用你的生成 a #define
,编译器也会看到/*
并给你一个错误,因为它不是有效的 C 代码(它是一个预处理指令)。
这似乎不是一件好事。
因为注释在预处理器运行之前(并且仅在之前)被替换为空格。如果您将字符粘贴在一起/
并*
使用预处理器,您会得到/*
这只是几个运算符。编辑:##
这种技术上的滥用创建/*
为具有未定义行为的单个令牌。您可以粘贴在一起> ## >
或< %:%: :
,尽管您不应该这样做。
请参阅 C99 的 §6.4.6 了解您可以构造的令牌,以及 6.10.3.3 了解连接过程。
如果您想使用预处理器注释某些代码,请使用
#if 0
...
#endif