1

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
  • Your compiler should be shouting warnings to you, because quite contrary to what you think the code doesn't work: It will give you undefined behavior. Listen to the compiler, and treat all warnings as errors. Commented Apr 23, 2023 at 20:26
  • 1
    Also, are you building for a 32-bit system? Where sizeof(int) just so happen to be equal to sizeof(int *)? Or if you're on a 64-bit system, doesn't the pointers use all 64 bits available to it, and the endianness just so happens to be so that the bits of the pointers match that of a 32-bit int? Try using pointers created some other way, for example global variables or returned by malloc. Commented Apr 23, 2023 at 20:29

2 Answers 2

5

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);
Sign up to request clarification or add additional context in comments.

10 Comments

The compiler is shouting, but it still works though. I'm using 64bit machine, so i believe it's the second option. Can u give me an example for a case it won't work?
the address of x for example is 7ffd39c9cd64 which is 140725572980068 in decimal. It is more the the max value of int...
@MatanCode Try putting either x or y (but not both) at file scope and see what happens.
@MatanCode If the pointer to x is 7ffd39c9cd64 then I guess the upper 32 bits of the pointer to y is exactly the same as for the pointer to x? Then you're only swapping the low 32 bits of the pointers. Use pointers to integers created in different scopes, for example x being local and y allocated of the heap or being a global variable. Where the upper 32 bits are different.
@MatanCode See my appended answer.
|
0
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

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.