【问题标题】:Why pre-processor gives a space?为什么预处理器给一个空间?
【发布时间】:2011-01-24 09:45:02
【问题描述】:

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

#define open /##*

#define close */

main()
{
        open commented line close
}

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

/* commented line */ 

但我得到了

/ * commented line */ 

让编译器显示错误

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

【问题讨论】:

  • 也许您应该添加“abusing_the_c_preprocessor”标签? ;)

标签: c-preprocessor stringification


【解决方案1】:

来自 GNU C 预处理器文档:

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

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

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

【讨论】:

    【解决方案2】:

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

    正如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++ = ' ';
    

    【讨论】:

      【解决方案3】:

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

      这似乎不是一件好事。

      【讨论】:

      • #define 是这里唯一的预处理指令。 /* 不是预处理器指令,但不清楚您指的是什么。
      • @Potatoswatter:预处理器负责在将代码传递给编译器之前移除 cmets。
      • 根据 C99 5.1.1.2/3,cmets 是空格,不是预处理标记。
      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

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

        #if 0
        ...
        #endif
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-01-25
          • 1970-01-01
          • 1970-01-01
          • 2010-12-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多