代码之家  ›  专栏  ›  技术社区  ›  David Z

定义是否应在宏周围添加空格?

  •  3
  • David Z  · 技术社区  · 15 年前

    我在看节目 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年以来,情况发生了变化吗?)

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

    4 回复  |  直到 9 年前
        1
  •  6
  •   David Z    15 年前

    预处理器操作令牌,而不是严格的文本。所以从技术上讲,它不会在两者之间“放置一个空格”,但是除非您明确地告诉它将两个令牌与 ## 接线员,不行。在这种情况下,两个 - 横穿宏行的被计算为两个不同的标记-都意味着一元减号,而不是减号。

    参见: http://en.wikipedia.org/wiki/C_preprocessor#Token_concatenation

        2
  •  11
  •   Adam Rosenfield    15 年前

    只有更老的预处理器没有插入额外的空间——请注意,原始条目是在20多年前的1988年提交的,当时C标准的1989年版本还没有标准化。你可以通过 -traditional-cpp 指向gcc预处理器的标志,使其模仿老式C预处理器的行为,而不是iso c预处理器。

        3
  •  5
  •   Michael Burr    15 年前

    根据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
  •  -1
  •   pts    15 年前

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