Home > Software engineering >  Why do we pass address instead of value as arguments to a swapping function in C?
Why do we pass address instead of value as arguments to a swapping function in C?

Time:08-10

I am solving the problem of swapping the value of two variables. I need to do it using a helper function. Now I've been studying the call-by-value and call-by-reference stuff.

My only confusion is when I'm passing the arguments to the swap function, why am I sending the address(&a, &b)? What actually happens when I'm sending the address instead of the value itself?

Here's the code

#include <stdio.h>
void swap(int a, int b) {
    int temp;
    temp = a;
    a = b;
    b = temp;
    printf("After swapping values in function(using call by value) a = %d, b = %d\n",a,b);
}
void swapref(int *a, int *b) {
    int temp2;
    temp2 = *a;
    *a=*b;
    *b=temp2;
    printf("After swapping values in function(using call by reference) a = %d, b = %d\n",*a,*b);
}
int main() {
    int a = 10, b = 20;
    printf("Before swapping the values in main a = %d, b = %d\n",a,b);

    swap(a,b);

    printf("After swapping values in main(using call by value) a = %d, b = %d\n",a,b);

    swapref(&a,&b); // <-- This is the line I'm talking about

    printf("After swapping values in main(using call by reference) a = %d, b = %d\n",a,b);
    return 0;
}

In the above code, what actually happens in the swapref(&a, &b) line?

CodePudding user response:

Passing the address is different than giving the value since you passe the exact memory case where your original variable (a and b) are stored. Like :

void swapref(int *a, int *b)

So when in the function you modify those value, you change the original ones.

Whereas passing variables values like :

void swap(int a, int b)

You're passing a copy of each variable, so the originals won't be touched.

CodePudding user response:

As you can see by the output of your program:

After swapping values in function(using call by value) a = 20, b = 10
After swapping values in main(using call by value) a = 10, b = 20
After swapping values in function(using call by reference) a = 20, b = 10
After swapping values in main(using call by reference) a = 20, b = 10

The variables are not actually swapped. Whenever passing a something as a parameter, its value is copied into the argument.

void by_val(int i) {
    i = 2;
    // the variable i in main will NOT be changed,
    // because this one is a copy
}

void by_ptr(int* i) {
    // This will change the i in main, because we didn't copy its value,
    // but copied the memory address of i variable in main.
    *i = 2;

    // Now we can make i point to an other variable than the main function i.
    // This will not update i, but it will update num.
    int num = 2;
    i = &num;
    *i = 3;
    
}

int main() {
    int i = 1;
    by_val(i);
    printf("%d\n", i); // "1"
    by_ptr(&i);
    printf("%d\n", i); // "2"
}

So in your first swap function, the values of the copies of (main) a and b are being swapped, not the values of (main) a and b. But in your second function, the values of (main) a and b are swapped, because you passed the memory addresses of the (main). The * operator makes the program use the values in the variables, the memory address is pointing to.

CodePudding user response:

swap() parameters are passed by copy, while swapref() ones are passed by reference (i.e. you pass the variable memory address, instead of its content).

  • * operator returns the value-pointed-to of a variable
  • & operator returns the address-of a variable

To better understand what happens, I suggest you to print their addresses

void swap(int a, int b) {
    int temp;
    temp = a;
    a = b;
    b = temp;
    printf("After swapping values in function (using call by value) [%p]a = %d, [%p]b = %d\n", &a, a, &b, b);
}
void swapref(int* a, int* b) {
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
    printf("After swapping values in function (using call by reference) [%p]a = %d, [%p]b = %d\n", &(*a), *a, &(*b), *b);
}

int main()
{
    int a = 10, b = 20;

    printf("Before swapping the values in main [%p]a = %d, [%p]b = %d\n", &a, a, &b, b);

    swap(a, b);

    printf("After swapping values in main (using call by value) [%p]a = %d, [%p]b = %d\n", &a, a, &b, b);

    swapref(&a, &b); // <-- This is the line I'm talking about

    printf("After swapping values in main (using call by reference) [%p]a = %d, [%p]b = %d\n", &a, a, &b, b);
    return 0;
}

Output:

Before swapping the values in main [000000A6B03BF834]a = 10, [000000A6B03BF854]b = 20
After swapping values in function(using call by value) [000000A6B03BF800]a = 20, [000000A6B03BF808]b = 10
After swapping values in main(using call by value) [000000A6B03BF834]a = 10, [000000A6B03BF854]b = 20
After swapping values in function(using call by reference) [000000A6B03BF834]a = 20, [000000A6B03BF854]b = 10
After swapping values in main(using call by reference) [000000A6B03BF834]a = 20, [000000A6B03BF854]b = 10

As you can notice, the variables used in swapref() present the same addresses as the ones that are passed to the function.

CodePudding user response:

It doesn't help that you're using the same names for different things. For the purpose of this answer, we're going to assume the variables in main are named x and y instead:

int main( void )
{
  int x = 10, y = 20;
  ...
  swap(x, y);
  ...
  swapref(&x, &y);
  ...
}

That will make the following discussion easier to follow.


The formal parameters a and b in swap are different objects in memory from the local variables x and y in main.

When you call

swap(x, y);

in main, the expressions x and y are fully evaluated and the results of those evaluations (10 and 20, respectively) are passed to swap and copied into its formal arguments.

Since a and b are different objects from x and y, exchanging the values of a and b has no effect on the values of x and y.


Just like with swap, the formal parameters a and b in swapref are different objects in memory from the local variables x and y. When you call

swapref(&x, &y);

the expressions &x and &y are fully evaluated, and the results of those evaluations (the addresses of x and y) are passed to swapref and copied into the formal arguments a and b.

This means the following relationships are true:

 a == &x // int * == int *
*a ==  x // int   == int
 b == &y // int * == int *
*b ==  y // int   == int

Again, since a and b in swapref are different objects in memory from x and y in main, changing the values of a and b in swapref has no effect on x and y. However, when you write new values to the expressions *a and *b in swapref, you're not changing the values of a and b but rather what a and b point to, which in this case is x and y.

You can kinda-sorta think of *a and *b as aliases for x and y - they're alternate names for the same objects. Writing

temp = *a;
*a = *b;
*b = temp;

is equivalent to writing

temp = x;
x = y;
y = temp;
  • Related