【问题标题】:What does the ## operator mean/do in this C macro? [duplicate]## 运算符在此 C 宏中的含义/作用是什么? [复制]
【发布时间】:2015-09-06 05:13:35
【问题描述】:
#define swap(t, x, y) \
  do { \
   t safe ## x ## y; \
   safe ## x ## y = x; \
   x = y; \
   y = safe ## x ## y; \
  } while (0)

代码交换类型为 t 的参数 x 和 y。

【问题讨论】:

  • 你得到了什么输出?
  • 双井号## 用于标记连接。谷歌也一样
  • 为了继续遵循关于 C 宏的不成文 (?) 规则,我建议您将宏命名为全部大写 ...#define SWAP(t, x, y)

标签: c function macros


【解决方案1】:

##(双数字符号)运算符在宏定义中给出的宏调用(文本和/或参数)中连接两个标记。 Read More

【讨论】:

    【解决方案2】:

    双井号## 用于标记连接。

    为简单起见,这就是您的代码在没有井号键的情况下的外观。

    #define swap(t, x, y) \
      do { \
       t safexy; \
       safexy = x; \
       x = y; \
       y = safexy; \
      } while (0)
    

    使用##时需要遵守以下规则

    • ## 运算符不能是 宏定义的替换列表。
    • ## 运算符前面的项目的最后一个标记是 与 ## 之后的项目的第一个标记连接 操作员。
    • 连接发生在参数中的任何宏之前 扩大。如果连接的结果是一个有效的宏 名称,即使出现也可用于进一步替换 在通常不可用的情况下。

    • 如果多个## 运算符和/或# 运算符出现在 宏定义的替换列表,评估的顺序 运算符未定义。

    更多了解read here

    【讨论】:

      【解决方案3】:

      当你调用这个宏时,例如这样:

      swap(double, a, b);
      

      它被内联代码替换以交换两个值,即:

      do {
         double safeab;
         safeab = a;
         a = b;
         b = safeab;
      } while (0);
      

      注意事项:

      • 交换需要一个临时变量。为了创建这个变量,类型必须是已知的。 (一些编译器允许您使用 typeof(a),但这不是标准的,因此不可移植。)
      • 临时变量的名称由要通过预处理器的串联运算符## 交换的变量的名称组成。此运算符仅在宏体中可用,并通过将相邻标记粘贴在一起来创建新标记。请注意,如果交换操作数之一是复合的,则名称创建失败,例如a[i]p->x。通过连接创建名称有点过于谨慎。因为交换发生在它自己的范围内,所以隐藏变量是安全的,当然那些被交换的除外。只需在常规命名约定之外选择一个名称,然后交叉手指即可。
      • do { ... } while (0) 包装器是使宏表现得像函数的常用方法,如果它们用作ifwhile 主体的唯一表达式,这一点很重要。
      • 末尾的反斜杠允许您将宏分散到多行。习惯上在最后将它们整齐排列,这样它们就不会弄乱代码。

      鉴于宏不适用于复合表达式,因此您不会购买太多。它也不是泛型类型,因为当您调用宏时,类型必须是已知的。编写一个用于交换的小静态函数;我认为这更清楚。

      C FAQ 对泛型交换宏也有疑问和强烈意见。

      【讨论】:

      • 因为无论如何你都不能交换复合表达式,我不确定'Given'子句是否真的适用。我想你只能交换……嗯,左值。
      • @JonathanLeffler:嗯,你可以交换,比如说,a[i]a[j]p->xp->y,不是吗?这不会连接到有效的变量名,也不是“简单”的单标记表达式。也许“复合表达”不是一个好词;我在这里使用了“compound”,因为它用于“compound literal”,即引用复合数据类型。
      • 顺便说一句,我也不确定问题是否完全与 ## 运算符有关,正如这里的每个人似乎都假设的那样。最初的,公认的相当模糊的问题标题是“这段代码是如何工作的?”。
      • 下标数组元素等表达式的公平点;精心制作的临时变量名被破坏了。我真的没有看到有什么其他东西(除了##)让 OP 感到困惑。
      • @Shyam:宏看起来像一个函数,所以在代码中它会像函数一样使用。但它扩展到不止一种陈述。如果你有if (x) MACRO(a); 并且它扩展到if (x) first(a); second(a); 你会感到惊讶:second(a) 将被无条件调用。包装器可以防止这种情况发生。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-16
      • 1970-01-01
      • 1970-01-01
      • 2017-04-24
      • 1970-01-01
      • 1970-01-01
      • 2015-10-15
      相关资源
      最近更新 更多