【问题标题】:Is #define supposed to add spaces around macros?#define 是否应该在宏周围添加空格?
【发布时间】:2009-05-08 20:29:35
【问题描述】:

我正在查看http://www0.us.ioccc.org/1988/westley.c 中的程序,在another SO answer 中提到 - 它应该打印 pi 的值,大约 3.142,但是当我编译并运行它时,我得到了0.250。看起来当 GCC 预处理器(测试的 4.1.2 和 3.4.6)在代码上运行时,它会转换

#define _ -F<00||--F-OO--;
_-_-_

-F<00||--F-OO--;- -F<00||--F-OO--;- -F<00||--F-OO--;

但我认为,要让程序正常运行,它应该是

-F<00||--F-OO--;--F<00||--F-OO--;--F<00||--F-OO--;

即GCC 在“宏”扩展之前插入了一个额外的空间。这是#define 应该工作的方式吗? (自 1988 年以来这种情况发生了变化吗?)

编辑:另外,任何有关如何防止这些空间出现的信息都将不胜感激。

【问题讨论】:

    标签: c gcc macros whitespace c-preprocessor


    【解决方案1】:

    只有更老的预处理器没有插入额外的空间——请注意,原始条目是在 20 多年前的 1988 年提交的,那时 1989 年版本的 C 标准还没有标准化。您可以将-traditional-cpp 标志传递给 GCC 预处理器,使其模仿老式 C 预处理器的行为,而不是 ISO C 预处理器。

    【讨论】:

    • 好消息。这提醒我,他们有时会使用 #define PASTE(x,y) x/**/y 之类的东西进行令牌粘贴,其中评论会消失得无影无踪。
    • 粘贴的这个习语促使标准委员会创建了一个正式的运算符。一旦他们指定注释将被一个空格替换,它就打破了成语。
    【解决方案2】:

    预处理器对标记进行操作,而不是严格的文本。所以从技术上讲,它不会在两者之间“放置一个空格”,但除非您明确告诉它将两个标记与 ## 运算符一起粘贴,否则它不会这样做。在这种情况下,跨宏行的两个 - 被计为两个不同的标记 - 都表示一元减号,而不是减量。

    另请参阅:http://en.wikipedia.org/wiki/C_preprocessor#Token_concatenation

    【讨论】:

    • 在这种情况下,我认为“-”是一元减法,而不是二元减法。
    • 我接受这个答案作为对正在发生的事情的最清楚的解释;-) 我根据 Chris 的评论对其进行了编辑(因为我接受了它,所以我认为准确性很重要)。
    【解决方案3】:

    来自 C99 标准:

    表单的预处理指令

    #定义标识符替换列表换行

    定义了一个类似对象的宏,它使宏名称的每个后续实例都被构成指令其余部分的预处理标记的替换列表替换。

    因此,宏在令牌上起作用,并且可以预期出现空白。

    您可以使用令牌粘贴运算符## 获得您想要的输出,但您需要使用一些更进一步的宏丑来做到这一点:

    #define PASTE2( x, y) x##y
    #define PASTE( x, y) PASTE2(x, y)
    
    #define _ -F<00||--F-OO--;
    
    
    PASTE(PASTE(PASTE(PASTE(_,-),_),-),_)
    

    所以我不确定这对你来说是不是一个真正的答案。

    您可以使用一组不那么难看的宏来获得您想要的表达式 - 仍然会有一些空格,但这些空格不会干扰创建“--”运算符:

    _ PASTE(-,_) PASTE(-,_)
    

    不过,我仍然怀疑这就是你想要的。

    【讨论】:

      【解决方案4】:

      是的,gcc 正在插入额外的空格(通过检查 gcc -E westley.c( 的标准输出输出来验证。据我所知,这种行为符合标准。

      【讨论】:

      • 很明显,OP 知道它是。他想知道是否应该这样做。
      • 克里斯是对的。我检查了 gcc -E 的输出,发现插入了多余的空格,因此提示我问这个问题。
      猜你喜欢
      • 2019-04-17
      相关资源
      最近更新 更多