为什么预处理器会占用空间?

时间:2010-03-06 07:35:54

标签: c-preprocessor stringification

我想使用预处理器评论一行:

#define open /##*

#define close */

main()
{
        open commented line close
}

当我做$gcc -E filename.c我期待

/* commented line */ 

但我得到了

/ * commented line */ 

以便编译器显示错误

为什么会给出不必要的空间?

5 个答案:

答案 0 :(得分:6)

来自GNU C预处理器文档:

  

但是,两个不能一起形成有效令牌的令牌无法粘贴在一起。例如,您无法以任何顺序将x与+连接。如果您尝试,预处理器会发出警告并发出两个令牌。是否在令牌之间放置空格是不确定的。在复杂的宏中发现'##'的不必要用法是很常见的。如果您收到此警告,则可能只需删除“##”即可。

在这种情况下,'*'和'/'不会形成有效的C或C ++令牌。因此,它们之间会有一个空间。

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

答案 1 :(得分:5)

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

正如CPP doc

所述
  

不能一起形成有效令牌的两个令牌不能粘贴在一起。例如,您无法以任何顺序将x+连接起来。

您可以通过粘贴其他无意义的内容来获取错误,例如/##++##-


关于空间,故意插入以避免创建评论并弄乱其余部分。来自GCC source code

    /* 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++ = ' ';

答案 2 :(得分:3)

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

这似乎不是一件好事。

答案 3 :(得分:3)

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

参见C99的§6.4.6,了解允许构建的令牌和6.10.3.3的连接过程。

答案 4 :(得分:0)

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

#if 0
...
#endif