可移植的C SWAP宏不需要一个“类型”参数,不使用的memcpy [英] Portable C SWAP macro which doesn't require a 'type' argument and doesn't use memcpy

查看:171
本文介绍了可移植的C SWAP宏不需要一个“类型”参数,不使用的memcpy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

交换宏的内搭一个类型差不多是人所共知的。

Swap macro's which take a type are fairly well known.

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

还有:
宏SWAP(T,X,Y)交换类型t 的两个参数

是否有可能实现这个功能而被...

Is it possible to implement this functionality while being...


  • 便携式(没有编译具体的typeof

  • 在不使用的函数调用,如的memcpy 结果
    (这是不放心得到优化出来,的这不是在我的测试至少的)

  • portable (no compiler specific typeof)
  • without using function calls such as memcpy
    (which isn't assured to get optimized out, it wasn't in my tests at least)

我想出了一个的缺陷的方法,它采用的是结构,定义为输入的大小。

I came up with a flawed method which uses a struct, defined to be the size of the input.

#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)

...但它可能会失败,如果临时结构被编译器填充的(根据GCC的 __包装__ 将工作,但那么它不再便携式)结果也可能有依赖于架构

... but it can fail if the temporary struct gets padded by the compiler (Depending on GCC's __packed__ would work but then its no longer portable)
It also may have issue with alignment depending on the architecture
.

推荐答案

我很好奇,想知道在何种情况下这种结构将得到填充,以及是否这种填充是符合的。

I am curious to know under which circumstances such a structure would get padded, and whether such padding would be conformant.

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

You can add a static check for sizeof(SWAP) == sizeof(a_) and use memcpy if the test fails (padding was inserted at the end of the SWAP structure).

另外,不要使用简单的名称,如 A B 在宏的身体,因为他们可以如果用户定义了这些标识符作为宏宏扩展。使用 A B 作为宏参数并不构成问题。

Also do not use simple names such as a and b in the body of the macro as they could be macro expanded if the user defined these identifiers as macros. Using a and b as macro arguments does not pose a problem.

#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)作为一个贫穷的芒尝试类型检查这个过度劳累宏。

You might want to add a check for sizeof(a) == sizeof(b) as a poor mans attempt to type checking this overworked macro.

这篇关于可移植的C SWAP宏不需要一个“类型”参数,不使用的memcpy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆