_generic




在C中实现通用交换宏 (4)

GMan开始尝试这种方法,将inline函数和宏结合起来进行编码。 此解决方案假设您拥有支持C99的现代C编译器,因为它使用复合文字

inline void swap_detail(void* p1, void* p2, void* tmp, size_t pSize)
{
   memcpy(tmp, p1, pSize);
   memcpy(p1, p2, pSize);
   memcpy(p2 , tmp, pSize);
}
#define SWAP(a, b) swap_detail(&(a), &(b), (char[(sizeof(a) == sizeof(b)) ? (ptrdiff_t)sizeof(a) : -1]){0}, sizeof(a))

这具有以下属性:

  • 它只评估aba
  • 它具有正确大小的编译时检查。
  • 它没有隐藏变量的命名问题。
  • 临时变量的大小在编译时计算,因此复合文字不是动态数组。

需要(ptrdiff_t) ,以便-1不会以静默方式提升为SIZE_MAX

该解决方案仍然存在两个缺点:

  1. 它不是类型安全的。 它只检查类型的大小,而不是它们的语义。 如果类型不同,比如说大小为8和uint64_tdouble ,就会遇到麻烦。

  2. 表达式必须允许&运算符适用。 因此,它不适用于使用register存储类声明的变量。

可能重复:
在c中是否有等价的std :: swap()

嗨伙计,

我正在尝试在C中编写通用交换宏的问题,我的宏看起来像这样:

#define swap(x,y) { x = x + y; y = x - y; x = x - y; }

它适用于整数和浮点数,但我不确定它是否有任何捕获。 如果通用宏它们意味着交换指针,字符等怎么办? 任何人都可以帮我写一个通用宏来交换每个输入吗?

谢谢


简单地说:你不能在C中创建一个通用的交换宏,至少, 没有一些风险或头痛 。 (见其他帖子。解释如下。)

宏很好,但是实际代码遇到的问题就是数据类型问题(如你所说)。 此外,宏在某种程度上是“愚蠢的”。 例如:

使用示例宏#define swap(x,y) { x = x + y; y = x - y; x = x - y; } #define swap(x,y) { x = x + y; y = x - y; x = x - y; } #define swap(x,y) { x = x + y; y = x - y; x = x - y; }swap(++x, y)变为{ ++x = ++x + y; y = ++x - y; ++x = ++x - y;} { ++x = ++x + y; y = ++x - y; ++x = ++x - y;} { ++x = ++x + y; y = ++x - y; ++x = ++x - y;}

如果你运行int x = 0, y = 0; swap(++x, y); int x = 0, y = 0; swap(++x, y); 你得到x=2, y=3而不是x=0, y=0 。 除此之外,如果宏中的任何临时变量出现在您的代码中,您可能会遇到一些烦人的错误。

您正在寻找的功能是作为模板在C ++中引入的。 你可以在C中得到的最接近的是对每种可想象的数据类型使用内联函数或者是一个相当复杂的宏(参见前面的宏观问题和之前的帖子)。

以下是使用C ++中的模板的解决方案:

template<typename T>
inline void swap(T &x, T &y)
{
    T tmp = x;
    x = y; y = tmp;
}

在C中你需要这样的东西:

inline void swap_int(int *x, int *y) { /* Code */ }
inline void swap_char(char *x, char *y) { /* Code */ }
// etc.

或者(如提到的那样)一个相当复杂的宏,它有可能是危险的。


根据标准,这不一定适用于int 。 想象一下xy分别为INT_MAXINT_MAX-1情况。 第一个加法语句将导致签名溢出,标准未定义。

对于int的交换宏,更可靠的实现是XOR交换算法


说真的,你需要在你的代码中进行多少交换,以便在给定解决方案的这个帖子中出现所有令人头疼的问题? 我的意思是,这不是一个10行复杂且容易出错的代码结构,它是一个众所周知的成语,有一个临时变量和三个简单的赋值。 如果您想节省空间,请将其写在您需要的地方,即使在一行中:

function foo ()
{
    int a, b, tmp;
    ...
    tmp = a; a = b; b = tmp;
    ....
}

或者使用“本地”宏,其中a和b更复杂。

#define SWAP(t,a,b) ( (t) = (a), (a) = (b), (b) = (t) )

function foo (pointer)
{
    int tmp;
    ...
    SWAP(tmp, pointer->structure.array[count+1], pointer->structure.array[count+2]);
    ...
}

#undef SWAP




generics