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

abu*_*ker 7 stringification c-preprocessor

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

#define open /##*

#define close */

main()
{
        open commented line close
}
Run Code Online (Sandbox Code Playgroud)

当我做$gcc -E filename.c我想到的

/* commented line */ 
Run Code Online (Sandbox Code Playgroud)

但我明白了

/ * commented line */ 
Run Code Online (Sandbox Code Playgroud)

这样编译器就会显示错误

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

Ste*_*n C 6

从GNU C预处理器文档:

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

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

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


ken*_*ytm 5

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

正如CPP文件所解释的那样:

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

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


关于空间,它是故意插入,以避免创建评论和搞乱其余部分.来自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++ = ' ';
Run Code Online (Sandbox Code Playgroud)


Gre*_*ill 3

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

这似乎不是一件好事。

  • 根据 C99 5.1.1.2/3,注释是空格,不是预处理标记。 (2认同)