discussing some technical aspects covering tools, frameworks, technologies etc (the areas where i m involved and getting experienced) - feel free to discuss!

Thursday, September 13, 2007

Pass by value Vs Pass by Reference

We all would have read the two terms "pass-by-value" and "pass-by-reference" especially when you deal with methods (which are also called as functions).

Let's just have a quick glance at both the terms with a small example.

The definition of these terms goes as follows.

Pass-by-value: A copy of the value is being passed from the calling method to the called method.

What exactly do you mean by copy of the value? In general, we tend to pass the variable for the value to be passed. In such case, whatever the value the variable holds is being copied and passed across. That means, you are taking a xerox of the o riginal value and pass the xeroxed copy to the called method.

What are the effects?
Since you have only passed the xeroxed copy and NOT the original value, whatever changes you do in the called method, the change is not reflected back to the original variable.

A Sample program for pass-by-value:

void changeValue(int a)
{
int b = ++a;
printf("changeValue -> a, b contain: %d,%d",a,b);
}

int changeAndReturn(int a)
{
int b = ++a;
printf("changeAndReturn -> a,b contain : %d,%d",a,b);
return b;
}

int main()
{
int i = 1;
changeValue(i);
j = i;
printf("\ni and j is : %d,%d\n",i,j);
printf("\ncalling changeAndReturn()..");
changeAndReturn(i);
j = i;
printf("\nNow i and j contain: %d,%d",i,j);
}


Output:
changeValue-> a, b contain: 2 2
i and j is: 1,1
calling changeAndReturn()..
changeAndReturn -> a,b contain: 2 2
Now i and j contain: 1 2


Explanation:
Let's see how exactly the values are dealt. In the main() method, you are calling changeValue() method as

changeValue(i);

At this time, the value of i (which is 1) is being copied (Remember! xeroxed) and the xeroxed copy is what getting passed to the changeValue() method. Inside the changeValue() method, you get (receive) the passed value in the variable name "a". Note: Even if you have received the passed argument as the same name "i" in the function, the compiler would treat both of them differently!

Soon after you take a xerox copy of the value of the variable and use it for calling functions, the connection between the copied value and the original value is cut. There is no relation between those two values and /or variables.

Inside the method changeValue(), we do the following steps:

(i) receive the value passed in the variable whose name is 'a' (implicit)
(ii) declare an int variable named 'b'
(iii) increment the received value in its variable 'a' and assign the incremented value to 'b'

Since because the original value ('i' in main) does NOT hold any relationship with its xeroxcopy ('a' here), the changes you do in the called function (incrementing the value in changeValue()) does NOT reflect back.

That's why in the main after the function call returned, the printf statement prints the value both i and j contain 0. Once the function call is returned, the present focus is in main() function and now we are assigning the value of 'i' to 'j' which is 0 only. This clearly shows that there is NO effect on the variable 'i' even after calling the function changeValue() which does some change to it actually.

Just to have an effect, we have one more method called changeAndReturn() which changes the value and returns it. In the calling function (main()), we get the returned value and assign it to 'j'. That's why the second set of output shows the incremented value '2' for both 'i' and 'j'.

Pass-by-reference: The memory address of the variable is being passed instead of making a copy of the value. This holds good for C, C++ languages (as far as i know as such).

What are the effects?
Since you pass the memory address itself to the function and you obtain the value from the received memory address inside the called function, you get the full control over the value. That means, whatever change you do, it will be reflecting in the original variable in the calling function eventhough you do NOT return either the memory address or value back.

It is because, you have played around with the memory directly instead of values and in both the calling and called functions, the values are obtained and manipulated with respect to memory only. So the change is reflected back.

Let's see a sample program for pass-by-reference:

Sample Program for pass-by-reference:

void changeValue(int *int_ptr)
{
//doing an increment operation on the 'dereferenced' pointer
int b = ++(*int_ptr);
printf("changeValue -> a, b contain: %d,%d",a,b);
}

int main()
{
int i = 1;
int *int_ptr = &i;
printf("\ncalling changeValue()..");

//Note: we are passing the pointer to the function! (the 'address')
changeValue(int_ptr);
//assigning the value of 'i' to 'j'
int j = i;
printf("\ni and j is : %d,%d\n",i,j);
}


Output:
changeValue-> a, b contain: 2 2

calling changeValue()..
i and j is: 2,2


Explanation:

If you carefully look at the implementation and way of calling the function changeValue(), it actually receives a pointer to an integer! that means, we are passing the 'memory address' of an integer variable.

Inside the function, we do the following steps:

(i) receive the address of the integer variable in the name 'int_ptr' (the same name as in the calling function, here main(). But remember! for the compiler, they both are different!)
(ii) we declare an integer variable 'b'
(iii) we dereference the pointer variable ('dereferencing' means obtaining the value present in the location where the pointer is pointing to)
(iv) we increment the value being obtained by the dereferencing operation
Note: here the value is incremented directly in the memory location
(v) and assign the incremented value to the variable 'b'

One important thing is that, we do NOT return any value back to the calling function. But the changes happend in the memory location directly in the called function (changeValue()). Once the control comes back to the calling function (main()), we are still accessing the value in the same memory location through the original variable 'i' and assigning to 'j'.

That's why we see both i and j having the value '2'.


About Me

ஏதோ பிறந்தோம், ஏதோ வாழ்ந்தோம் என்றிருப்பதல்ல வாழ்க்கை! எப்படி வாழ்ந்தோம் என்பதும் ஒரு அங்கம். வாழக் கிடைத்த வாழ்க்கையில், ஒரு சிலருக்காவது வசந்தத்தின் முகவரியை அறிமுகம் செய்தோமேயானால் அதுவே வசீகரத்தின் வனப்பைக் கூட்டும்!