便携式 C SWAP 宏,不需要“type”参数,也不使用 memcpy

2023-11-29

采用某种类型的交换宏是众所周知的。

#define SWAP(type, a_, b_) do {        \
    type SWAP, *a = &(a_), *b = &(b_); \
    SWAP = *a;                         \
    *a = *b;                           \
    *b = SWAP;                         \
} while (0)

also: 宏 SWAP(t,x,y) 交换两个类型 t 的参数

是否可以在...的同时实现此功能?

  • 可移植(没有编译器特定的typeof)
  • 不使用函数调用,例如memcpy
    (这并不能保证得到优化,至少在我的测试中没有)

我想出了一个flawed使用结构体的方法,定义为输入的大小。

#define SWAP(a_, b_) do \
{ \
    struct { \
        char dummy_data[sizeof(a_)]; \
    } SWAP, *a = (void *)(&(a_)), *b = (void *)(&(b_)); \
    /* ensure sizes match */ \
    { char t[(sizeof(a_) == sizeof(*a)) ? 1 : -1]; (void)t; } \
    /* check types are compatible */ \
    (void)(0 ? (&(a_) == &(b_)) : 0); \
    SWAP = *a; \
    *a = *b; \
    *b = SWAP; \
} while (0)

...但如果临时的,它可能会失败struct由编译器填充(取决于海湾合作委员会__packed__可以工作,但它不再便携)
根据架构的不同,它也可能存在对齐问题
.


我很想知道在什么情况下会填充这样的结构,以及这样的填充是否符合要求。

您可以添加静态检查sizeof(SWAP) == sizeof(a_)并使用memcpy如果测试失败(在末尾插入了填充SWAP结构)。

也不要使用简单的名称,例如a and b在宏的主体中,因为如果用户将这些标识符定义为宏,则它们可以被宏扩展。使用a and b因为宏参数不会造成问题。

#define SWAP(a, b) do {                             \
    struct {                                        \
        char a_[sizeof(a)];                         \
    } SWAP, *a_ = (void *)&(a), *b_ = (void *)&(b); \
        if (sizeof(SWAP) == sizeof(a)) {            \
            SWAP = *a_; *a_ = *b_; *b_ = SWAP;      \
        } else if (a_ != b_) {                      \
            memcpy(&SWAP, a_, sizeof(a));           \
            memcpy(a_, b_, sizeof(a));              \
            memcpy(b_, &SWAP, sizeof(a));           \
        }                                           \
    } while (0)

您可能想要添加检查sizeof(a) == sizeof(b)作为一个穷人尝试对这个过度劳累的宏进行类型检查。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

便携式 C SWAP 宏,不需要“type”参数,也不使用 memcpy 的相关文章

随机推荐