0

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?

  • Because you otherwise pass *copies* of the items to swap. They get swapped locally, with no effect on the original variables, and are forgotten at the end of the function. Passing their address allows the function to swap the caller's values. – Weather Vane Aug 09 '22 at 10:10
  • 5
    This is explaind in your beginner's C text book. – Jabberwocky Aug 09 '22 at 10:11
  • C doesn't really have "call by reference" at all, only "call by value". For array argument and parameters, C gives the impression of using call by reference, but that is because arrays in function arguments are converted to pointers to the first element, and function parameters declared as arrays are "adjusted" to be declared as pointers. – Ian Abbott Aug 09 '22 at 11:20

4 Answers4

1

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.

Brian
  • 55
  • 4
1

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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Tenobaal
  • 637
  • 1
  • 16
0

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.

mikyll98
  • 1,195
  • 3
  • 8
  • 29
0

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;
John Bode
  • 119,563
  • 19
  • 122
  • 198