7

我想使用预处理器注释一行:

#define open /##*

#define close */

main()
{
        open commented line close
}

当我这样做时,$gcc -E filename.c我期望

/* commented line */ 

但我得到了

/ * commented line */ 

以便编译器显示错误

为什么它给了一个不需要的空间?

4

5 回答 5

6

来自 GNU C 预处理器文档:

但是,不能将不一起形成有效令牌的两个令牌粘贴在一起。例如,您不能以任一顺序将 x 与 + 连接。如果您尝试,预处理器会发出警告并发出两个令牌。是否在标记之间放置空白是未定义的。在复杂的宏中发现“##”的不必要使用是很常见的。如果您收到此警告,很可能您可以简单地删除“##”。

在这种情况下,“*”和“/”不会形成有效的 C 或 C++ 标记。所以它们被发射出来,它们之间有一个空间。

(除此之外:即使您设法在 C 预处理器的输出中插入“注释”,您也可能会遇到 C 编译错误。那里不应该有任何注释。)

于 2010-03-06T07:56:22.983 回答
5

错误是因为/*不是有效的令牌。

正如CPP 文档所解释的:

不能一起形成有效标记的两个标记不能粘贴在一起。例如,您不能以任一顺序连接xwith +

您可以通过粘贴其他无意义的东西(例如/##++##-.


关于空间,它是故意插入的,以避免创建评论并弄乱其余部分。从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++ = ' ';
于 2010-03-06T07:57:54.993 回答
3

预处理器以 C 编译器可以理解的形式运行并生成代码。它只处理你的代码一次,所以即使你可以/*用你的生成 a #define,编译器也会看到/*并给你一个错误,因为它不是有效的 C 代码(它是一个预处理指令)。

这似乎不是一件好事。

于 2010-03-06T07:41:15.740 回答
3

因为注释在预处理器运行之前(并且仅在之前)被替换为空格。如果您将字符粘贴在一起/*使用预处理器,您会得到/*这只是几个运算符。编辑:##这种技术上的滥用创建/*为具有未定义行为的单个令牌。您可以粘贴在一起> ## >< %:%: :,尽管您不应该这样做。

请参阅 C99 的 §6.4.6 了解您可以构造的令牌,以及 6.10.3.3 了解连接过程。

于 2010-03-06T07:41:37.747 回答
0

如果您想使用预处理器注释某些代码,请使用

#if 0
...
#endif
于 2010-03-06T09:23:41.177 回答