3

我正在查看http://www0.us.ioccc.org/1988/westley.c上的程序,在另一个 SO 答案中提到- 它应该打印 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

4 回答 4

11

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

于 2009-05-08T21:09:19.543 回答
7

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

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

于 2009-05-08T20:42:02.180 回答
5

来自 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(-,_)

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

于 2009-05-08T20:44:42.177 回答
-1

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

于 2009-05-08T20:31:49.197 回答