交换两个void指针很容易,不需要使用任何额外的内存:
void* p1;
void* p2;
//...
p1 = ((uintptr_t)p1) ^ ((uintptr_t)p2);
p2 = ((uintptr_t)p1) ^ ((uintptr_t)p2);
p1 = ((uintptr_t)p1) ^ ((uintptr_t)p2);
但是交换函数指针必须使用另一个指针吗? (因为它们不能保证适合任何整数类型)。
void (*p1)();
void (*p2)();
//...
void (*tmp)() = p1;
p1 = p2;
p2 = tmp;
有人能举例说明一个完全可移植的方法,它会在不使用临时变量的情况下交换函数指针吗?
答案 0 :(得分:3)
我认为这很有效,因为允许通过(unsigned)char进行别名处理:
void (*p1)();
void (*p2)();
for (size_t i = 0; i < sizeof(p1); ++i) {
((unsigned char *)&p1)[i] ^= ((unsigned char *)&p2)[i]
}
for (size_t i = 0; i < sizeof(p2); ++i) {
((unsigned char *)&p2)[i] ^= ((unsigned char *)&p1)[i]
}
for (size_t i = 0; i < sizeof(p1); ++i) {
((unsigned char *)&p1)[i] ^= ((unsigned char *)&p2)[i]
}
答案 1 :(得分:0)
我宁愿这样写(见下文,但是):
uintptr_t up1 = (uintptr_t)p1;
uintptr_t up2 = (uintptr_t)p2;
p1 ^= p2;
p2 ^= p1;
p1 ^= p2;
在大多数具有sizeof(uintptr_t)
&lt; =寄存器大小的架构上,这是三个指令== 3个时钟,可能与其他版本一样多(除非转换成本额外)。但是,我更喜欢大多数架构的临时变体。
警告: 不安全:6.3.2.3p1个状态“void *
可以在指向任何对象的指针之间安全转换类型“和7.20.1.4p1状态”unitptr_t
可以包含void *
“,3.15将术语对象限制为仅限数据存储。函数驻留在代码存储中。 (感谢评论)
所以,不要将它应用于函数指针!
注意,这不像temp-version那么明显,如果它检测到temp-version的模式,编译器可能会很好地使用这段代码。
答案 2 :(得分:-3)
使用xor swap algoritm:
*p1 = *p1 ^ *p2;
*p2 = *p1 ^ *p2;
*p1 = *p1 ^ *p2;