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.
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).
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’).
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:
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.
* 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.
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
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 with
var)
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.
Pass
values
using global variables
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);
std::cout
<< "\n" << baz;
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);
std::cout << "\n"
<< baz;
std::cin.get();
return(0);
}
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.
Code:
#include <iostream>
int foo(int bar)
{
bar = (bar + bar);
return(bar);
}
int main()
{
int baz = 5;
std::cout <<
foo(baz);
std::cout << "\n"
<< baz;
std::cin.get();
return(0);
}
References:
http://www.simonhuggins.com/courses/cbasics/course_notes/session19.htm