我正在查看http://www0.us.ioccc.org/1988/westley.c中提到的another SO answer中的程序 - 它应该打印pi的值,大约3.142,但是当我编译并运行它时,我得到{{1} }。看起来当GCC预处理器(经过测试的4.1.2和3.4.6)在代码上运行时,它会转换
0.250
到
#define _ -F<00||--F-OO--;
_-_-_
但我认为,要使该计划有效,它应该是
-F<00||--F-OO--;- -F<00||--F-OO--;- -F<00||--F-OO--;
即。 GCC在“宏观”扩张之前插入了一个额外的空间。这是-F<00||--F-OO--;--F<00||--F-OO--;--F<00||--F-OO--;
的工作方式吗? (自1988年以来有变化吗?)
编辑:此外,任何有关如何防止这些空间出现的信息都将受到赞赏。
答案 0 :(得分:11)
只有很多较旧的预处理器没有插入额外的空间 - 请注意,原始条目是在20年前的1988年提交的,而1989年版本的C标准已经标准化。您可以将-traditional-cpp
标志传递给GCC预处理器,这会导致它模仿旧式C预处理器的行为,而不是ISO C预处理器。
答案 1 :(得分:6)
预处理器对令牌进行操作,而不是严格的文本。所以从技术上来说,它并没有“间隔”,但除非你明确告诉它将两个令牌与##
运算符一起粘贴,否则它不会这样做。在这种情况下,跨越宏行的两个-
被计为两个不同的标记 - 两者都意味着一元减去,而不是减少。
另见:http://en.wikipedia.org/wiki/C_preprocessor#Token_concatenation
答案 2 :(得分:5)
来自C99标准:
表单
的预处理指令#define identifier replacement-list new-line
定义了一个类似于对象的宏,它使宏名称的每个后续实例都被构成指令其余部分的预处理标记的替换列表替换。
因此宏可以处理令牌,并且可以预期空白。
你可以使用令牌粘贴操作符##
获得所需的输出,但是你需要使用一些进一步的宏难度来完成它:
#define PASTE2( x, y) x##y
#define PASTE( x, y) PASTE2(x, y)
#define _ -F<00||--F-OO--;
PASTE(PASTE(PASTE(PASTE(_,-),_),-),_)
所以我不确定这对你来说是真正的答案。
您可以使用一组不那么丑陋的宏来获取所需的表达式 - 仍然会有一些空格,但这些空格不会干扰创建“--
”运算符:
_ PASTE(-,_) PASTE(-,_)
但我仍然怀疑这是你想要的。
答案 3 :(得分:-1)
是的,gcc正在插入额外的空格(通过检查gcc -E westley.c
的stdout输出来验证(。据我所知,这种行为符合标准。