交换2个没有临时变量的函数指针

时间:2015-06-25 14:26:32

标签: c function-pointers

交换两个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;

有人能举例说明一个完全可移植的方法,它会在不使用临时变量的情况下交换函数指针吗?

3 个答案:

答案 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;