Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的交换指针地址_C_Pointers_Swap - Fatal编程技术网

C语言中的交换指针地址

C语言中的交换指针地址,c,pointers,swap,C,Pointers,Swap,我需要对C语言中的两个指针进行超高性能交换(地址,而不是它们指向的对象)。我知道地址是对齐的(16的倍数)并且是连续的,我已经检查过在每次执行中都会保留这些地址。代码如下: Nodo a __attribute__((aligned(8))), b __attribute__((aligned(4))); Nodo *nodo_superior __attribute__((aligned(4))); nodo_superior = &a; Nodo * nodo_actual __at

我需要对C语言中的两个指针进行超高性能交换(地址,而不是它们指向的对象)。我知道地址是对齐的(16的倍数)并且是连续的,我已经检查过在每次执行中都会保留这些地址。代码如下:

Nodo a __attribute__((aligned(8))), b __attribute__((aligned(4)));
Nodo *nodo_superior __attribute__((aligned(4)));
nodo_superior = &a;
Nodo * nodo_actual __attribute__((aligned(4)));
nodo_actual=&b;
printf("%ld %ld\n", nodo_superior, nodo_actual);
控制台上的结果如下(请注意,第一个地址应该是“over”对齐的,以便下一个方法工作):

现在要交换地址,我想更改每个指针的第5位:

nodo_superior ^= 16; 
nodo_actual ^= 16;
但是,不幸的是,C编译器不允许这样做,因为整数不能与指针值混合:这是一个错误,而不是警告。如果我尝试在一个联合中包含指针,如下所示:

union {
    Nodo * nodo_actual;
    int local_int;
} na;
想做一个类似于:

na.local_int ^= 16;
然后性能会下降,因为(我想)如果nodo_actual在一个联合中,编译器无法对其应用/推断优化。
有没有办法强迫编译器按照我的要求运行?当然,我可以改变生成的汇编器,但是我不认为这是一个好的选择,

如果你想切换每一个指针的5位,你可以写:

nodo_superior = (Nodo *)((uintptr_t)nodo_superior ^ 16);
uintptr\u t
是一种整数类型,它(如果存在)保证能够在不丢失信息的情况下保存指针值

它的目的是通过平面内存模型上的明显同构来实现,因此它应该适合您(尽管首先要测试它)


另外,您应该使用
%p
打印指针,而不是导致未定义行为的
%ld
。要打印
uintptru\t

,如果要切换每个指针的第5位,请执行以下操作:

nodo_superior = (Nodo *)((uintptr_t)nodo_superior ^ 16);
uintptr\u t
是一种整数类型,它(如果存在)保证能够在不丢失信息的情况下保存指针值

它的目的是通过平面内存模型上的明显同构来实现,因此它应该适合您(尽管首先要测试它)


另外,您应该使用
%p
打印指针,而不是导致未定义行为的
%ld
。打印
uintptpr\t

我不确定我是否真正理解您所说的“交换两个指针”的意思。似乎您有一对节点,并且您希望从另一个节点的地址计算一个节点的地址

类似的问题是,当您有两个数字(例如,玩家编号为1和2)并且希望将玩家编号从1更改为2,反之亦然。通常的技巧是计算

  opponent = (1+2) - player ;
您可以使用指针玩类似的把戏,因为允许使用某些算术:

int main(int argc, char **argv)
{
    struct Node x;
    struct Node y;

    printf("x is at %p,  y at %p\n", &x, &y);

    struct Node * one = &x;
    struct Node * other = &x + (&y - one); // (&x + &y) - one

    printf("if one is at %p,  the other is at %p\n", one, other);

    one = &y;
    other = &x + (&y - one);

    printf("if one is at %p,  the other is at %p\n", one, other);

    return 0;
}

我不确定我真的理解你所说的“交换两个指针”是什么意思。似乎您有一对节点,并且您希望从另一个节点的地址计算一个节点的地址

类似的问题是,当您有两个数字(例如,玩家编号为1和2)并且希望将玩家编号从1更改为2,反之亦然。通常的技巧是计算

  opponent = (1+2) - player ;
您可以使用指针玩类似的把戏,因为允许使用某些算术:

int main(int argc, char **argv)
{
    struct Node x;
    struct Node y;

    printf("x is at %p,  y at %p\n", &x, &y);

    struct Node * one = &x;
    struct Node * other = &x + (&y - one); // (&x + &y) - one

    printf("if one is at %p,  the other is at %p\n", one, other);

    one = &y;
    other = &x + (&y - one);

    printf("if one is at %p,  the other is at %p\n", one, other);

    return 0;
}

交换最好采用“旧方法”,使用临时变量

Nodo* Swap= a; a= b; b= Swap;
这需要2次读取和2次写入

“智能”解决方案


需要2次读取、2次异或和2次写入。

交换最好采用“旧方法”,使用临时变量

Nodo* Swap= a; a= b; b= Swap;
这需要2次读取和2次写入

“智能”解决方案


花费2次读取、2次XOR和2次写入。

不要假设指针和int的大小相同……不要假设指针和int的大小相同……虽然大小很好,但听起来他的编译器一般不允许按位操作指针类型。正如您所说的,测试将确认。@donjuedo这就是为什么您首先将其转换为整数。虽然大小很好,但听起来他的编译器一般不允许对指针类型进行按位操作。正如你所说的,测试可以确认。@donjuedo这就是为什么你首先将它转换为整数。我计算了3次读取和3次写入。你似乎嘲笑的“聪明”解决方案是两读两写;碰巧xor分解为读写操作。在任何一种情况下,一个优化关闭的微基准都会使xor版本的速度持续加快,高达17%。不,交换变量是临时的,并保存在寄存器中。关闭优化时进行基准测试并不能帮助您进行优化。公平地说,使用-O1,它们编译为相同的移动集。我计算了3次读取和3次写入。你似乎嘲笑的“聪明”解决方案是两读两写;碰巧xor分解为读写操作。在任何一种情况下,一个优化关闭的微基准都会使xor版本的速度持续加快,高达17%。不,交换变量是临时的,并保存在寄存器中。关闭优化时进行基准测试并不能帮助您进行优化。公平地说,使用-O1时,它们编译为同一组移动。