如何在 C 宏定义中包含双引号?

How to include a double quote in a C macro defintion?

提问人:Andrew Merrill 提问时间:11/4/2023 最后编辑:Andrew Merrill 更新时间:11/5/2023 访问量:101

问:

我有以下测试程序:

#define q "

int main() {
    printf(q hello world q);
}

使用 gcc 编译它(我在 Ubuntu 上尝试了 12.3 和 11.4 版本)会产生此错误:在第 1 行。使用 clang(Apple clang 版本 11.0.0)编译会在第 4 行产生错误。error: missing terminating " charactererror: expected expression

现在,我一直认为,当编译 C 程序时,预处理器首先运行,处理所有预处理器指令,然后预处理器的输出由编译器正确读取。

通过 gcc 预处理器 (gcc -E) 运行此测试程序会产生警告,但没有错误,并产生以下合理的输出:

int main() {
    printf(" hello world ");
}

该程序现在将编译而不会出错并且运行良好。因此,虽然我不能直接编译原始程序,但如果我手动运行预处理器并编译结果,那么它就可以工作了。这违反了我对预处理器和编译器如何协同工作的理解(显然是错误的)。

所以,我有两个问题:

  1. 是否可以在 C 宏的定义中包含双引号字符(但不能包含其中两个)?

  2. 在此示例中,如果我手动运行预处理器,则预处理器和编译器会发生什么情况,但当我手动运行预处理器时,预处理器和编译器不允许编译和运行?

C-预处理器

评论

7赞 Barmar 11/4/2023
你不能这么做。预处理器在令牌级别运行,而不是在字符级别运行。字符串文本是单个标记。
2赞 Barmar 11/4/2023
也许最初的 C 编译器按照您想象的方式工作,但现代 C 编译器却没有。预处理器集成到解析器中,它不是为下一个传递生成文本源的单独传递。因此,将具有误导性的输出。gcc -E
3赞 Craig Estey 11/4/2023
也许不是你想要的,但你可以做:然后:#define q(x) #xprintf(q(hello world));
0赞 phuclv 11/4/2023
预处理处于第 3 阶段

答:

9赞 Chris Dodd 11/4/2023 #1

C 预处理器处理的是标记(和标记序列),而不是单个字符,标记化发生在预处理之前。这意味着你不能在预处理器中操作不是标记的东西——裸露的东西不是标记,它是字符串文字标记的一部分。"

通过使用更通用的宏处理器(如 m4),您也许可以执行更像您想要的事情