在OSX上,为什么/ usr / bin / cpp不支持宏参数的字符串化,而gcc -E和clang -E呢?

时间:2012-02-29 23:11:55

标签: c llvm llvm-gcc

如果我在foo.c中有以下代码

#define P(x) printf("%s\n", #x)

void main() {
  P(3 == 4);
}

调用gcc -E foo.c将输出:

int main() {
  printf("%s\n", "3 == 4");
}

请注意,#运算符已经为宏参数x字符串化了字符串。但是,当我调用/ usr / bin / cpp时,我得到以下内容......但未正确扩展。

int main() {
  printf("%s\n", #3 == 4);
}

2 个答案:

答案 0 :(得分:11)

cpp命令可能不是一致的C预处理器,而是传统的ANSI C预处理器。我的猜测是,Apple使其工作正常,因为Darwin是一个BSD系统和一些使用cpp命令进行非C目的的遗留BSD软件(如配置文件的宏处理)如果你放弃一个符合要求的C预处理器就会以微妙的方式破解。

在任何情况下,都不应使用cpp命令,因为您永远不知道自己会得到什么。 c99 -E是调用C预处理器的POSIX一致方式,$CC -E可能是在Makefile中执行此操作的正确方法。

答案 1 :(得分:5)

看起来由于某种原因,Lion上的cpp(我的版本与您相同)的行为就像启用了-traditional开关一样。我可以重现您在其他cpp二进制文件(Linux,FreeBSD)上观察到的输出,但仅限于使用-traditional开关时。

经过调查,结果发现Mac OS X上的/usr/bin/cpp是一个开头的脚本:

#!/bin/sh
#
# Transitional front end to CCCP to make it behave like (Reiser) CCP:
#       specifies -traditional
#       doesn't search gcc-include

这个脚本指定后,显然没有办法用另一个选项撤消-traditional。一种解决方法是使用特定的已安装版本,例如cpp-4.2。在我的系统上使用cpp-4.2可以产生所需的扩展。