Pass by value and
pass by
reference (and reference variables)
Pass by value and Pass by Reference
We have seen as to how to pass values to a function
through
arguments. Actually there are two ways to pass values to a function
through
arguments. These two methods are explained below with examples.
Pass By Value: Example:
{
//body of function
}
int main ( )
{
int b = 10;
check (b);
}
In this function, ‘x’ is a parameter and ‘b’ (which
is the
value to be passed) is the argument. In this case the value of ‘b’ (the
argument) is copied in ‘x’ (the parameter). Hence the parameter is
actually a
copy of the argument. The function will operate only on the copy and not
on the
original argument. This method is known as PASS BY VALUE. So far we have
dealt
only with pass by value (except when passing arrays to functions).
#include <iostream.h>
int square (int x)
{
return x*x;
}
int main ( )
{
int num = 10;
int answer;
answer = square(num);
cout<<"Answer is "<<answer; // answer is 100
cout<<" Value of a is "<<num; // num will be 10
return 0;
}
You can see that the value of ‘num’ is unchanged. The
function ‘square’ works only on the parameter (i.e. on x ). It does not
work on
the original variable that was passed (i.e it doesn't work on ‘num’).
The diagram makes it
quite
clear as to what happens when we call square(num). The following
initialization
takes place:
int x =
num;
and the function
square( )
operates only on a copy of num.
Pass By Reference
In pass by reference method, the function will
operate on the
original variable itself. It doesn't work on a copy of the argument but
works on
the argument itself. Consider the same square function example:
#include <iostream.h>
void square (int *x)
{
*x = (*x) * (*x);
}
int main ( )
{
int num = 10;
square(&num);
cout<<" Value of num is "<<num; // Value of num is 100
return 0;
}
As you can see the result will be that the value of a
is 100.
The idea is simple: the argument passed is the address of the variable
‘num’.
The parameter of ‘square’ function is a pointer pointing to type
integer. The
address of ‘num’ is assigned to this pointer. You can analyze it as
follows:
&num is passed to int *x, therefore it is the same as:
This means that ‘x’ is a pointer to an integer and has the address of the variable num.int *x = #
Within the function we have:
* when used before a pointer will give the value
stored at
that particular address. Hence we find the product of ‘num’ and store it
in
‘num’ itself. i.e. the value of 100 is stored in the address of ‘num’
instead of
10 which was originally present there. The
diagram below illustrates the difference between pass by value and pass
by
reference. Now when we dereference ‘x’ we are actually manipulating the
value
stored in ‘num’.
This is the pass-by-reference method which was used
in C. In
C++ there is a different approach. Of course you can use the above
method, but
C++ has its own special way.
Whenever the function accesses the parameter it receives, it does so without reference to the original argument which cannot be overwritten; nor can a volatile argument change the value of the parameter once the function is entered. Pass by value semantics can be contrasted with pass by reference semantics, which C does not directly support.
Within the function, accesses of the formal parameter, either for reading or for writing, directly access the same variable that the caller of the function passed in as its argument.
C does not directly support pass by reference because it always uses pass by value, but a programmer can implement pass by reference by passing a pointer to the variable that the programmer wants passed by reference.
Pass values using function parameters
The first is to pass data into the function using input parameters, as we looked at a few sessions back. Our program would look something like this:-
The result is then returned from the function (of type float as specified at the start of the function's definition line and prototype line), which has been calculated to be one divided by the original value.
Control is passed back to the original program, where one_over(f) is replaced with the return value - e.g. if f contained 2 then the value returned would be 1/2 (i.e. 1 divided by 2) - i.e. 0.5, so one_over(f) is replaced with 0.5, and the line in main() becomes res = 0.5. So res gets filled with the value 0.5 in this example.
Another method, which is generally frowned upon by many, is to use variables that are available to every function in your program. These are called global variables.
To declare a global variable and make it available to all functions, just to the definition out of a specific function, and put it towards the top of your program - just above the main() function should be fine. This implies that the scope of the variable has changed to be outside all functions, and therefore available to all functions. Our program can now look like this:-
It would be possible to provide input as shown in the previous section, by passing a parameter, and providing the ouput as the res variable, and then we could keep the res variable local to the main() function. This would mean that we could re-use the one_over function in different functions without the fear of overwriting the result.
We still run the risk of losing our input, if the one_over function is used in several different places - we risk mixing the inputs and outputs up of if we use it several different times. This is the advantage of keeping variables local, and passing parameters - this keeps the risk of overwriting something unintentionally to a minimum, and is the reason why you should not use global variables unless really necessary.
A typical example of where it would be okay to use a global variable might be a variable that is truly only ever used for one purpose throughout a program - for example score or high_score in a game, or userid in a password-protected application.
MORE EXAMPLES:
Pointer
Passing by pointer is where you pass a function a pointer to the object you want worked with. You are not actually changing the object itself, just the local or temporary copy that you have made with the pointer.
This code is wrong. Both output 10 and I can not for the life of me figure out why that is. Perhaps I am using pointers wrong.
Reference
Passing by reference means that you don't pass the value of an object, you are passing the object itself. There are no copies made, only the original object is what is worked with.
Value
Passing by value means that you are taking a copy of what has been passed to the function, work with it in the function, but do not modify the original value.
References:
http://www.simonhuggins.com/courses/cbasics/course_notes/session19.htm
aliases: Pass
by value
From clc-wiki
Pass by value is a term describing function call semantics. To pass by value means that the argument (a variable, constant or other expression) is evaluated and a copy of its value is then passed to the function.Whenever the function accesses the parameter it receives, it does so without reference to the original argument which cannot be overwritten; nor can a volatile argument change the value of the parameter once the function is entered. Pass by value semantics can be contrasted with pass by reference semantics, which C does not directly support.
Quick examples
The program below#include <stdio.h> void foo(int x); int main(void) { int i = 5; printf("In main(): %d\n", i); foo(i); printf("In main(): %d\n", i); return 0; } void foo(int x) { printf("In foo(): %d\n", x); x = 10; printf("In foo(): %d\n", x); }prints
In main(): 5 In foo(): 5 In foo(): 10 In main(): 5
aliases: Pass by reference
From clc-wiki
Pass by reference is a term that describes a part of the semantics of function parameters. To pass by reference means that within the function, the formal parameter is or acts as an alias (reference) for the function argument - so pass by reference is only meaningful when the function's argument is a variable (note that "parameter" and "argument" have slightly different meanings - consult the link in the "See Also" section below).Within the function, accesses of the formal parameter, either for reading or for writing, directly access the same variable that the caller of the function passed in as its argument.
C does not directly support pass by reference because it always uses pass by value, but a programmer can implement pass by reference by passing a pointer to the variable that the programmer wants passed by reference.
Quick examples
The program below#include <stdio.h> void foo(int *x); int main(void) { int i = 5; printf("In main(): %d\n", i); foo(&i); printf("In main(): %d\n", i); return 0; } void foo(int *x) { printf("In foo(): %d\n", *x); *x = 10; printf("In foo(): %d\n", *x); }prints
In main(): 5 In foo(): 5 In foo(): 10 In main(): 10
Notes on proper usage
Pass by reference and call by reference are synonyms and are specific terms of art that indicate direct syntactical support in the language. Referring to the C mechanism used in the example above - passing a pointer to a variable in order to access the variable within the function - as "pass by reference" is technically incorrect. This is because within the function the language's syntax requires the dereferencing operator to be applied to the pointer, whereas true pass by reference, such as supported by Pascal (parameters declared withvar)
and C++ (parameters declared with &), does not have
that requirement. Better and more correct is to refer to the C
mechanism as "passing a reference".
Pass values using function parameters
The first is to pass data into the function using input parameters, as we looked at a few sessions back. Our program would look something like this:-
main()
{ |
float f,res; | this is the scope of the f variable
scanf("%f",&f); |
res = one_over(f); |
printf(" res is %3.2f", res ); |
}
float one_over(float amt)
{
float j; |
if (amt==0) amt==1; | this is the scope of the j variable
j = 1 / amt; | and the amt parameter variable
return j; |
}We can see that we are passing the i variable into the one_over function. This gets copied into the amt local variable inside the function. This can then be changed if necessary (as it is here to ensure that we never divide by zero, although this is not a very good solution to the problem!).
The result is then returned from the function (of type float as specified at the start of the function's definition line and prototype line), which has been calculated to be one divided by the original value.
Control is passed back to the original program, where one_over(f) is replaced with the return value - e.g. if f contained 2 then the value returned would be 1/2 (i.e. 1 divided by 2) - i.e. 0.5, so one_over(f) is replaced with 0.5, and the line in main() becomes res = 0.5. So res gets filled with the value 0.5 in this example.
Another method, which is generally frowned upon by many, is to use variables that are available to every function in your program. These are called global variables.
To declare a global variable and make it available to all functions, just to the definition out of a specific function, and put it towards the top of your program - just above the main() function should be fine. This implies that the scope of the variable has changed to be outside all functions, and therefore available to all functions. Our program can now look like this:-
float f,res;
main() |
{ |
scanf("%f",&f); |
one_over; | this is the scope
printf(" res is %3.2f", res ); | of the res and f variables
} |
|
void one_over; |
{ |
float amt; | |
amt = f; | this is the scope |
if (amt==0) amt==1; | of the amt variable |
res = 1 / amt; | |
} |
In this case, we have placed both the input (variable f) and
output
(variable res) as global variables. By doing so, we must always
make sure
we set variable f before we call the one_over function, as
it is
now providing the input. We must also make sure that the variables res
is set before the function ends, as this is now providing the output.
It would be possible to provide input as shown in the previous section, by passing a parameter, and providing the ouput as the res variable, and then we could keep the res variable local to the main() function. This would mean that we could re-use the one_over function in different functions without the fear of overwriting the result.
We still run the risk of losing our input, if the one_over function is used in several different places - we risk mixing the inputs and outputs up of if we use it several different times. This is the advantage of keeping variables local, and passing parameters - this keeps the risk of overwriting something unintentionally to a minimum, and is the reason why you should not use global variables unless really necessary.
A typical example of where it would be okay to use a global variable might be a variable that is truly only ever used for one purpose throughout a program - for example score or high_score in a game, or userid in a password-protected application.
MORE EXAMPLES:
Pointer
Passing by pointer is where you pass a function a pointer to the object you want worked with. You are not actually changing the object itself, just the local or temporary copy that you have made with the pointer.
This code is wrong. Both output 10 and I can not for the life of me figure out why that is. Perhaps I am using pointers wrong.
Code:
#include <iostream>int foo(int *bar){ *bar = (*bar + *bar); return(*bar);}int main(){ int baz = 5; int *pbaz = &baz; std::cout << foo(pbaz); //
Should equal 10 std::cout
<< "\n" << baz; // Should equal 5 std::cin.get(); return(0);}Reference
Passing by reference means that you don't pass the value of an object, you are passing the object itself. There are no copies made, only the original object is what is worked with.
Code:
#include <iostream>int foo(int &bar){ bar = (bar + bar); return(bar);}int main(){ int baz = 5; std::cout <<
foo(baz); // Should equal 10 std::cout << "\n"
<< baz; //
Should equal 10 std::cin.get(); return(0);} Passing by value means that you are taking a copy of what has been passed to the function, work with it in the function, but do not modify the original value.
Code:
#include <iostream>int foo(int bar){ bar = (bar + bar); return(bar);}int main(){ int baz = 5; std::cout <<
foo(baz); // Should equal 10 std::cout << "\n"
<< baz; //
Should equal 5 std::cin.get(); return(0);} References:
http://www.simonhuggins.com/courses/cbasics/course_notes/session19.htm
No comments:
Post a Comment