【问题标题】:paste operator in macros在宏中粘贴运算符
【发布时间】:2021-08-21 16:51:36
【问题描述】:

我找到了以下sn-p的代码。

#define f(g,g2) g##g2
main() {

    int var12=100;
    printf("%d",f(var,12));

}

我知道这会将 f(var,12) 转换为 var12 。

我的问题是在宏定义中,他们为什么不直接写以下内容:

#define f(g,g2) gg2

为什么我们需要 ## 来连接文本,而不是自己连接它?

【问题讨论】:

  • 你可以自己试试。如果您使用 gcc 或 clang,请使用 -E 编译并查看预处理器的输出。
  • 您阅读过GNU cpp 的文档吗?顺便说一句,在某些情况下,您可以生成 C 代码(例如,使用 GPP 预处理器)
  • @Basile:哎呀。也许将 OP 指向该书的特定部分?
  • @RobertHarvey:“yikes”是什么意思?我没有提到的最好的字典(我是法国人)
  • 这意味着 OP 可能不需要整本圣经,只需要一两章。

标签: c macros


【解决方案1】:

如果写入gg2,预处理器会将其视为单个标记。预处理器无法理解这是gg2 的串联。

【讨论】:

  • 你是说## 不是在这里转义的#
  • @RobertHarvey 不,单个哈希是字符串化运算符。双散列是连接运算符。他们是两个完全不同的运营商。就像-x--x 意味着两个完全不同的东西一样。
  • 所以转义哈希是一个上下文相关的操作?
  • @RobertHarvey 我不知道你在想什么语言。没有任何方法可以在 C 预处理器中转义散列(黑客和误导除外)。参见例如this question
【解决方案2】:
   #define f(g,g2) g##g2

我认为这是不可读的糟糕代码。它至少需要一个评论(给出一些动机、解释等......),像f 这样的短名称是没有意义的。

我的问题是在宏定义中,他们为什么不直接写以下内容:

#define f(g,g2) gg2

有了这样的宏定义,f(x,y) 仍然会扩展为标记 gg2,即使作者希望扩展为 xy

请花时间阅读例如GNU cpp(和你的编译器,可能是 GCC)的文档以及后来的一些 C 标准,如 n1570 或更好。

还可以考虑通过(在某些情况下)生成 C 代码(受 GNU bisonGNU m4GPP 启发)来设计您的软件。您的构建机器(例如,您的 Makefile for GNU make)会根据您的需要进行处理。在某些情况下(例如,程序运行几个小时的 CPU 时间),您可能会考虑做一些partial evaluation 并在运行时生成专门的代码(例如,使用libgccjitGNU lightning)。 Pitrat 在Artificial Beings, the conscience of a conscious machine 上的书在整本书中解释和论证了这个想法。

不要忘记在编译器中启用所有警告和调试信息(例如,使用 GCC 使用 gcc -Wall -Wextra -g)并学习使用调试器(例如 GNU gdb)。

在 Linux 系统上,我有时喜欢在运行时生成一些(或多或少是临时的)C 代码(来自某种abstract syntax tree),然后将该代码编译为plugin,然后将dlopen(3) 该插件编译为@ 987654337@ 在里面。举个愚蠢的例子,看看我的manydl.c 程序(以证明你可以在同一个程序中生成数十万个 C 文件和插件)。对于严肃的例子,请阅读书籍。

您还可以阅读有关Common LispRust 的书籍;两者都有比 C 提供的更丰富的macro 系统。

【讨论】:

  • 我看了N1570,将近八百页。 OP 真的需要知道所有这些才能确定## 吗?
  • 我猜 OP 可以买一本关于 C 编程的短书。我的建议是去一些大学学习有关 C 编程的课程 - 人类教师通常比读书更好
猜你喜欢
  • 2012-02-18
  • 1970-01-01
  • 2022-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多