Why regular swap works with a pointer-to-pointer variable?

79 Views Asked by At

I know the difference between these two functions: Swap(int *x, int *y) vs Swap(int **x, int **y).

But, I'm not sure how this kind of code works. How is it possible to swap the address which the pointers point at with a regular swap() type?

For example, I believe that a local pointer-variable a is created and it points to &ptr_x, so when I do dereference *x it equals to &x.

So, temp (and also *a and *b which also function as integers) can hold the actual address of the x/y and that's why it works?

void swap(int *a, int *b)
{
   int temp = *a;
   *a = *b;
   *b = temp;
}


int main()
{
   printf("in main:\n");

    int x = 2;
    int y = 8;

    int *ptr_x = &x;
    int *ptr_y = &y;

    printf("ptr_x points to = %p\n", ptr_x);
    printf("ptr_y points to = %p\n\n", ptr_y);

    swap(&ptr_x, &ptr_y);

    printf("ptr_x points to = %p\n", ptr_x);
    printf("ptr_y points to = %p\n", ptr_y);

    return 0;
}
2

There are 2 best solutions below

10
Vlad from Moscow On

The code is invalid. At least the compiler should issue a message that there are assignments (initializations) of pointers of different types without castings.

That is there is no implicit conversion between the pointer types int *, the type of the parameters, and int **, the type of argument expressions.

In general the function invokes undefined behavior because it is not necessary that an object of the type int is large enough to be able to store a pointer value.

It seems your program works either because sizeof( int * ) is equal to sizeof( int ) or values of addresses are not large and can be stored in objects of the type int. Or there are swapped only low-significant parts of the pointers that are equal in size to sizeof( int ) while most significant parts are the same for the both pointers.

To show that the code is invalid just use one pointer that points to a variable with automatic storage duration and other that points to a dynamically allocated memory.

Here is a demonstration program.

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

void swap(int *a, int *b)
{
   int temp = *a;
   *a = *b;
   *b = temp;
}

int main( void ) 
{
    int x;

    int *ptr_x = &x;
    int *ptr_y = malloc( sizeof( int ) );

    printf( "ptr_x = %p\n", ( void * )ptr_x );
    printf( "ptr_y = %p\n", ( void * )ptr_y );

    swap( ( int * )&ptr_x, ( int * )&ptr_y);

    printf( "ptr_x = %p\n", ( void * )ptr_x );
    printf( "ptr_y = %p\n", ( void * )ptr_y );

    // This can produce a run-time error 
    //free( ptr_x );  
}

The program output might look like for example

ptr_x = 0x7ffdcf002d98
ptr_y = 0x564608597eb0
ptr_x = 0x7ffd08597eb0
ptr_y = 0x5646cf002d98

As you can see there are swapped only less significant parts of the pointers that fit in object of the type int.

That is the expressions *a and *b within the function swap do not yield full values of pointers because they have the type int.

As a trick you could declare and define the function the following way:)

#include <stdint.h>

void swap(intptr_t *a, intptr_t *b)
{
   intptr_t temp = *a;
   *a = *b;
   *b = temp;
}

//...

swap( ( intptr_t * )&ptr_x, ( intptr_t * )&ptr_y);
0
Muzzammil Sarwar On
void swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

This swap function is excepting 2 pointers while you are passing addresses of pointer variables which has a type of int**. You will get undefined behavior because of type mismatch. So first you need to update:
swap(&ptr_x, &ptr_y);
to
swap(ptr_x, ptr_y);
The rest i would advise you to go through this link to understand how pointers are used to swap the values by call by reference method: https://www.studymite.com/blog/swapping-values-using-pointer-in-c