可移植的C SWAP宏不需要一个“类型”参数,不使用的memcpy [英] Portable C SWAP macro which doesn't require a 'type' argument and doesn't use 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屋!