0

I wanted to implement a swap function that works with all data types. I now know that this is not easily possible without malloc etc. But my real confusion is about why the following functions work with different data types:

//short int unsigned long
void swapInt(char* a, char* b)
{
   char tmp = *a;
   *a = *b;
   *b = tmp;
}

//double long
void swapDouble(void **pptr1, void **pptr2) 
{   
   void *temp1 = *pptr1; 

   *pptr1 = *pptr2;        
   *pptr2 = temp1;
}

//float
void swapFloat(void *a, void *b){
   int aux; 
   aux = *(int*)(a);//
   *(int*)(a) = *(int*)(b); 
   *(int*)(b) = aux; 
}

int main()
{
   #define SIZE 5
   int array[SIZE]={1,2,2,2,5};
   
   printf("before:\n ");
   for(int i=0; i < SIZE; i++)
       printf("%d ", array[i]);
           
   swapInt(&array[0], &array[4]);  
   printf("\n");
   
   printf("after:\n ");    
   for(int i=0; i < SIZE; i++)
       printf("%d ", array[i]);
       
   return 0;
}

The output of the main as it is shown in the code block was: before:
1 2 2 2 5
after:
5 2 2 2 1

If I change the array to double or float its: before:
1.000000 2.000000 2.000000 2.000000 5.000000
after:
1.000000 2.000000 2.000000 2.000000 5.000000

Testing it with the other functions, it still gives different results for different data types. Please explain this to me, it's really frustrating.

EDIT: I used this online compiler https://www.onlinegdb.com/online_c_compiler the warnings I get are following: main.c:37:12: warning: passing argument 1 of ‘swapInt’ from incompatible pointer type [-Wincompatible-pointer-types]
main.c:4:6: note: expected ‘char *’ but argument is of type ‘int *’
main.c:37:23: warning: passing argument 2 of ‘swapInt’ from incompatible pointer type [-Wincompatible-pointer-types]
main.c:4:6: note: expected ‘char *’ but argument is of type ‘int *’ And it works, or I wouldn't have said it works. I tried different functions I found on stack overflow and now I'm confused why they work or seem to work.

8
  • float and int may not be the same size or have the same memory alignment. In order for your swap to work correctly, you'll need to pass a size_t paramter for the size of the data type, and copy byte for byte (char or unsigned char). Commented Jun 29, 2020 at 3:19
  • 1
    Why do your swap functions take char * arguments for int, void ** for double, and void * for float? First step is to fix those to be void swapInt(int *a, int *b) and similar. The way it is now, it doesn't work even for ints, try for example to set the first element of array to -1 instead of 1. Commented Jun 29, 2020 at 3:19
  • Don't you get compiler warnings? If so - fix them. If not - make sure to increase the compilers warning level. Commented Jun 29, 2020 at 3:33
  • @dxiv sounds obvious tiping it but for int it should be void swapInt(int a, int *b), for double void swapDouble(doublea, double*b) etc? Commented Jun 29, 2020 at 5:33
  • @vokitori No, both arguments have to be pointers, so void swapInt(int *a, int *b). Commented Jun 29, 2020 at 5:40

1 Answer 1

1

It doesn't even work for int variables except possibly on systems where sizeof int is 1. Try swapping 1 and 258. I expect that you'll end up with 2 and 257 (though that is by no means something you can rely on).

You need to copy the right number of bytes, and you must do so in a way that doesn't violate alignment rules.

You can use the following:

void swap(void *a, void *b, size_t size) {
   char buf[size];
   memmove(buf, a, size);
   memmove(a, b, size);
   memmove(b, buf, size);
}

Example invocation:

int a = 1;
int b = 258;
printf("%d, %d\n", a, b);
swap(&a, &b, sizeof a);
printf("%d, %d\n", a, b);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.