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 = #
*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;