0

I have a quick question about using XOR two swap two string literals.

so I have the following:

#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
}

As you can see, I used binary operation XOR to for the intSwap. However, when I tried to do the same thing with swapString, it's not working.

I get error message saying: invalid operands to binary ^ (have ‘char *’ and ‘char *’)

Do you know how to use XOR to swap two string literals? Is it possible in C? Thanks ahead!!

djechlin
  • 59,258
  • 35
  • 162
  • 290
Victoria J.
  • 323
  • 2
  • 12
  • 2
    I hope you are not going to use this code in any production application. If you do, you have to add extra logic to make sure that calling `intSwap(&a, &a)` doesn't mess things up. – R Sahu Apr 20 '14 at 03:32
  • Why not just simply use a temporary. It's usually faster. – Petr Skocik May 25 '18 at 12:35
  • @RSahu: Or just make the pointers `restrict` and leave it up to the caller, same way `memcpy` does. – ShadowRanger Feb 22 '23 at 23:34

3 Answers3

9

There are no bitwise operations on pointers. The only "arithmetic" operations that can act on them are + and - (and their childer ++, --, += and -=). So you need to cast to intptr_t (or preferably uintptr_t when doing bitwise operations) and back.

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;
}

Anyway, it's a bad practice and won't save you any cycles. The compilers will recognize swaps using simple assignments and optimize it for you. Good compilers even recognize those XOR pessimizations and convert them back to the more efficient MOVs. Here are some examples. As you can see, the above function will be compiled to the following instructions

pointerXorSwap(int**, int**):
        mov     rax, QWORD PTR [rdi]
        mov     rdx, QWORD PTR [rsi]
        mov     QWORD PTR [rdi], rdx
        mov     QWORD PTR [rsi], rax
        ret
phuclv
  • 37,963
  • 15
  • 156
  • 475
4

If you're using C99 or greater, you need to cast the char * to intptr_t before operating, then cast back into a char * after operating.

Your error message:

invalid operands to binary ^ (have ‘char *’ and ‘char *’)

Tells you that you while you got the concept right, the operator ^ doesn't work on pointers.

Note that if your goal is to do this without using an extra variable (note this is not actually more efficient on modern compilers), you can do this using addition and subtraction, which pointers do support well enough. See this site for details.

intptr_t is an integer type that's intended to hold pointer values. Note intptr_t is not strictly speaking fully portable (there may not be an integer type that can hold pointers) per this SO answer.

Community
  • 1
  • 1
djechlin
  • 59,258
  • 35
  • 162
  • 290
1

*a=*b; means one char of b will be copied to a, not the whole string. The same applies to swapString function so this will produce the wrong value.

If you try the same with a string with length 1 this will work

phuclv
  • 37,963
  • 15
  • 156
  • 475
vijayky88
  • 134
  • 9