【问题标题】:Swap two pointers using XOR使用 XOR 交换两个指针
【发布时间】:2014-06-04 08:58:09
【问题描述】:

我有一个关于使用 XOR 两个交换两个字符串文字的快速问题。

所以我有以下内容:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void intSwap(int *a, int *b){
    *a=*a^*b;
    *b=*a^*b;
    *a=*a^*b;
}


void swapString(char **a, char **b){
    char *temp=*a;
    *a=*b;
    *b=temp;
}

void main(){
    char *s= "ha";
    char *t= "Oh";

    printf("%s and %s \n",s,t); // prints ha Oh
    swapString(&s,&t);
    printf("%s and %s \n",s,t); // prints Oh ha


    int a=10;
    int b=5;
    printf("%d %d\n",a,b); //print 10 5
    intSwap(&a,&b);
    printf("%d %d\n",a,b); //print 5 10
}

如您所见,我对 intSwap 使用了二进制操作 XOR。但是,当我尝试用 swapString 做同样的事情时,它不起作用。

我收到错误消息:二进制 ^ 的操作数无效(有 'char *' 和 'char *')

你知道如何使用 XOR 交换两个字符串文字吗?在C中可能吗?先谢谢了!!

【问题讨论】:

  • 我希望您不要在任何生产应用程序中使用此代码。如果这样做,则必须添加额外的逻辑以确保调用 intSwap(&amp;a, &amp;a) 不会搞砸。
  • 为什么不直接使用临时的。它通常更快。

标签: c swap xor


【解决方案1】:

*a=*b; 表示b 的一个字符将被复制到a,而不是整个字符串。这同样适用于swapString 函数,因此这将产生错误的值。

如果你对长度为 1 的字符串尝试同样的操作,这将起作用

【讨论】:

    【解决方案2】:

    指针没有按位操作。唯一可以作用于它们的“算术”运算是+-(以及它们的子++--+=-=)。所以你需要转换为intptr_t(或者最好是uintptr_t,在进行按位运算时)并返回。

    void pointerXorSwap(int **x, int **y){
        uintptr_t a = (uintptr_t)*x;
        uintptr_t b = (uintptr_t)*y;
    
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
    
        *x = (int*)a;
        *y = (int*)b;
    }
    

    无论如何,这是一种不好的做法,不会为您节省任何周期。编译器将使用简单的分配识别交换并为您优化它。优秀的编译器甚至可以识别这些 XOR 悲观化并将它们转换回更高效的 MOV Here are some examples。可以看到,上面的函数会被编译成如下指令

    pointerXorSwap(int**, int**):
            mov     rax, QWORD PTR [rdi]
            mov     rdx, QWORD PTR [rsi]
            mov     QWORD PTR [rdi], rdx
            mov     QWORD PTR [rsi], rax
            ret
    

    【讨论】:

      【解决方案3】:

      如果您使用的是 C99 或更高版本,则需要在操作前将 char * 转换为 intptr_t,然后在操作后将其转换回 char *

      您的错误信息:

      二进制 ^ 的无效操作数(有 'char *' 和 'char *')

      告诉你,当你的概念正确时,运算符 ^ 不适用于指针。

      请注意,如果您的目标是在不使用额外变量的情况下执行此操作(请注意,这不是实际上在现代编译器上更有效),您可以使用指针支持的加法和减法来执行此操作足够好。 See this site了解详情。

      intptr_t 是用于保存指针值的整数类型。注意intptr_t 严格来说并不是完全可移植的(可能没有可以保存指针的整数类型)per this SO answer

      【讨论】:

        猜你喜欢
        • 2012-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多