简体   繁体   English

C 中的 Hygenic 宏

[英]Hygenic macros in C

The C FAQ declares that a generic SWAP macro in C is essentially impossible and not worth the effort. C FAQ声明C中的通用 SWAP 宏基本上是不可能的,也不值得付出努力。 That sounds like a challenge to me.这对我来说听起来像是一个挑战。

It cites 2 main difficulties:它列举了两个主要困难:

  1. Finding a suitable type to use as a temporary variable.寻找合适的类型用作临时变量。 There are hacks involving char[] arrays and memcopy, but this sort of solution fails on things like SWAP(my_int, my_float) .有一些涉及 char[] 数组和 memcopy 的技巧,但是这种解决方案在SWAP(my_int, my_float)类的东西上失败了。 A lot of compilers support decltype style operators that make this easy, but they are nonstandard.许多编译器都支持decltype风格的操作符,这使得这很容易,但它们是非标准的。 For now I will admit defeat and just ask the user to supply a suitable type as the third argument.现在我承认失败,只要求用户提供合适的类型作为第三个参数。
  2. Finding a safe name for a temporary variable.为临时变量寻找安全名称。 This is something I think I have a solution for.这是我认为我有解决方案的事情。 I can use the stringify operator # to stringify the input arguments and compare them to prospective temporary variable names to find one that doesn't match.我可以使用 stringify 运算符#将输入参数字符串化,并将它们与预期的临时变量名称进行比较,以找到不匹配的名称。
#include <stdio.h>

#define SWAP(a,b,type)                          \
do {                                            \
    if ((#a[0] != 'a') && (#b[0] != 'a')){      \
        type a_temp = a;                        \
        a = b;                                  \
        b = a_temp;                             \
    }else                                       \
    if ((#a[0] != 'b') && (#b[0] != 'b')){      \
        type b_temp = a;                        \
        a = b;                                  \
        b = b_temp;                             \
    }else                                       \
    if ((#a[0] != 'c') && (#b[0] != 'c')){      \
        type c_temp = a;                        \
        a = b;                                  \
        b = c_temp;                             \
    }                                           \
} while(0)

int main()
{
    int a_temp = 10, b_temp = 20, c_temp = 30;

    printf("a_temp = %d, b_temp = %d, c_temp = %d\n", a_temp, b_temp, c_temp);
    SWAP(a_temp, b_temp, int);
    printf("a_temp = %d, b_temp = %d, c_temp = %d\n", a_temp, b_temp, c_temp);
    SWAP(a_temp, c_temp, int);
    printf("a_temp = %d, b_temp = %d, c_temp = %d\n", a_temp, b_temp, c_temp);
    SWAP(b_temp, c_temp, int);
    printf("a_temp = %d, b_temp = %d, c_temp = %d\n", a_temp, b_temp, c_temp);

    return 0;
}

I've seen the issue of accidental capture brought up in many discussions and not seen anyone mention that you could do this, either to recommend or condemn it.我已经在许多讨论中看到了意外捕获的问题,但没有看到任何人提到您可以这样做,无论是推荐还是谴责它。 Is this a good idea?这是一个好主意吗?

This will fail in some cases if the variables are lvalue expressions, eg, if you have int *a_temp and int *b_temp , and you SWAP(*a_temp, *b_temp, int) .如果变量是左值表达式,这将在某些情况下失败,例如,如果您有int *a_tempint *b_temp ,并且您使用SWAP(*a_temp, *b_temp, int) And since the macro is silently using "common" names like a_temp , it might break if there is something like #define a_temp *a .并且由于宏默默地使用诸如a_temp类的“常见”名称,因此如果存在诸如#define a_temp *a类的a_temp ,它可能会中断。

And anyway, it is arguably not generic since you have to pass the type: SWAP(a, b, int) is not fundamentally different from SWAPINT(a, b) .无论如何,它可以说不是通用的,因为您必须传递类型: SWAP(a, b, int)SWAPINT(a, b)没有根本区别。 If we accept passing the type, could we also accept passing the name of the temporary variable?如果我们接受传递类型,我们是否也接受传递临时变量的名称? Or even a fixed temporary variable name like _tmpswap0123456789 – after all, we are accepting the far more common name SWAP to be now defined as this macro, so worrying about the name of a temporary variable inside it seems secondary.或者甚至是像_tmpswap0123456789这样的固定临时变量名——毕竟,我们接受现在定义为这个宏的更常见的名称SWAP ,因此担心它内部的临时变量的名称似乎是次要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM