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

Kel*_*ton 2 c llvm llvm-gcc

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

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

void main() {
  P(3 == 4);
}
Run Code Online (Sandbox Code Playgroud)

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

int main() {
  printf("%s\n", "3 == 4");
}
Run Code Online (Sandbox Code Playgroud)

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

int main() {
  printf("%s\n", #3 == 4);
}
Run Code Online (Sandbox Code Playgroud)

R..*_*R.. 11

cpp命令可能不是一致的C预处理器,而是作为传统的ANSI C预处理器.我的猜测是,苹果公司的工作方式是这样的,因为Darwin是一个BSD系统,一些破坏的传统BSD软件使用该cpp命令进行非C目的(如配置文件的宏处理)如果放入符合条件的C,会以微妙的方式破解预处理器取而代之.

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


Gre*_*ill 5

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

在研究了这个之后,事实证明/usr/bin/cpp在Mac OS X上是一个像这样开始的脚本:

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

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