

\documentstyle{article}

\setlength{\oddsidemargin}{0in}
\setlength{\evensidemargin}{0in}
\setlength{\topmargin}{0.0in}
\setlength{\headheight}{0in}
\setlength{\headsep}{0in}
\setlength{\textwidth}{6.5in}
\setlength{\textheight}{9.4in}
\setlength{\parindent}{0in}
\setlength{\parskip}{0.12in}

\begin{document}

\newcommand{\bfs}[1]{{\bf #1}}

\begin{center}
{\LARGE\bf 

Parameters in C Functions

}
\end{center}

\bigskip

\section{Technical Summary}

Functions operate in C essentially like functions and procedures do in
Pascal.  However, just as the address nature of pointers is more explicit
in C than in Pascal, the address nature of call-by-reference parameters
is more explicit in C than in Pascal.

For example, consider the Pascal procedure

\begin{verbatim}
procedure MinMax(X,Y:integer; var Min,Max:integer);

begin
   if X < Y then
      begin
      Min:=X;
      Max:=Y
      end
   else
      begin
      Min:=Y;
      Max:=X
      end
end;
\end{verbatim}

After execution of the code

\begin{verbatim}
var A,B,SmallerOne,BiggerOne : integer;
...
...
A:=50;  B:=12;
MinMax(A,B,SmallerOne,BiggerOne);
\end{verbatim}

SmallerOne will be 12 and BiggerOne will be 50.

Recall that:  X, Y, Min and Max are called {\bf formal parameters}; A, B, 
SmallerOne and BiggerOne are called \bfs{actual parameters}; X and Y 
are termed \bfs{call-by-value parameters}, while Min and Max are called
\bfs{call-by-reference parameters}.  Call-by-value is indicated by
absence of the \bfs{var} construct, while call-by-reference is indicated
by its presence.

You were probably taught to use call-by-reference in any setting in which
the parameter value gets changed.  In the example above, Min and Max get
changed, so we use call-by-reference, while A and B don't get changed, so
we use call-by-value.  Though Pascal does not make this explicit, what is
really happening is that call-by-reference means that the \underline{address}
of the actual parameter is passed to the function or procedure, while under
call-by-value, the \underline{value} of the parameter is passed.

If you think about this, it makes good sense.  Say I have a procedure R
which has one formal parameter, and my code calls the procedure with the
actual parameter L.  Suppose L originally had the value 290, and that R
is supposed to change L to 54.  How in the world would R be able to make
that change under call-by-value?  It couldn't!  If I just tell R that L is
currently 290 but I don't tell R where L is in memory, there is no way
L can place 54 in that memory location.  Under call-by-reference, I tell
R that L is in location (say) 7006, and then there is no problem; R simply
places 54 into that memory location.

Again, this is what Pascal does, but it is all hidden from the programmer;
the \underline{compiler} will decide whether to send a value or an address
to the procedure.  By contrast, in the C language, the programmer must do 
this himself/herself.\footnote{Technically, we would say that C does not
provide the call-by-reference option; all parameters are call-by-value.
When doing C's analog of Pascal's call-by-reference, we are still doing
call-by-value, with the ``value'' in this case being an address.}

Here is the above example, implemented in C:

\begin{verbatim}
void MinMax(X,Y,MinAdrs,MaxAdrs)
   int X,Y,*MinAdrs,*MaxAdrs;

{  if (X < Y)  {
      *MinAdrs = X;
      *MaxAdrs = Y;
   }
   else  {
      *MinAdrs = Y;
      *MaxAdrs = X;
   }
}
\end{verbatim}

As in Pascal, the formal parameters are declared within parentheses right
after the function name.  But unlike Pascal, the \underline{types}
of the parameters are then given outside the parentheses.\footnote{Though
in ANSI C, the types are stated similarly to Pascal, i.e. the heading
of MinMax here would be

   void MinMax(int X, int Y, int *MinAdrs, int *MaxAdrs)

}  

By the way, it is crucial to place the braces at the proper places.  For
example, if we write the first few lines above as

\begin{verbatim}
void MinMax(X,Y,MinAdrs,MaxAdrs)

{  int X,Y,*MinAdrs,*MaxAdrs;

   if (X < Y)  {
\end{verbatim}

this would be wrong.  If we are lucky, the compiler will say so; if not,
the compiler will treat X, Y, etc. as local variables, not parameters,
and our program won't work correctly.
Here is the code calling it:

\begin{verbatim}
int A,B,SmallerOne,BiggerOne;
...
...
MinMax(A,B,&SmallerOne,&BiggerOne);
\end{verbatim}

First, a brief remark on the reserved word \bfs{void}:  This means that
the function MinMax has no type, e.g. is not of type \bfs{int} or any
other type; it does not return a value.  In other words, MinMax is 
analogous to a Pascal procedure, not a Pascal function.  Writing 
\bfs{void} here serves to remind us of that fact, though its use is 
optional.

Now, let's look at the parameters.  For example, I have changed the name
of the third parameter, from Min in the Pascal case to MinAdrs here.  Of
course, I can use whatever names I wish, but I have chosen the name MinAdrs
to remind myself that this parameter is an address.  This can be seen from
the `*' in the parameter declaration line,

\begin{verbatim}
int X,Y,*MinAdrs,*MaxAdrs;
\end{verbatim}

as well as from the `\&' in the call:

\begin{verbatim}
MinMax(A,B,&SmallerOne,&BiggerOne);
\end{verbatim}

So, as promised earlier, I really am explicitly passing an address for
this variable.

Since it is an address, I have to use `*' to {\bf dereference}, e.g. in the
line

\begin{verbatim}
*MinAdrs = X;
\end{verbatim}

which means, ``copy X to the object pointed to by MinAdrs.''  Since
MinAdrs contained the address of SmallerOne, the result will be exactly
the same as if I had done

\begin{verbatim}
SmallerOne = X;
\end{verbatim}

\section{Example}

\subsection{Script File}

To illustrate these principles, we show below a function MakeChange which,
as its name implies, makes change.  The calling module supplies a price
and the amount tendered, and the function then reports the number of quarters,
dimes, nickels and pennies needed for the change.

\begin{verbatim}
  1  Script started on Thu Apr 30 12:42:03 1992
  2  heather% cat MakeChange.c
  3  
  4  /* data for test program */
  5  int Price,AmountTendered,Quarters,Dimes,Nickels,Cents;
  6  
  7  
  8  char *DenomNamePtr[4] = {"quarter","dime","nickel","cent"};
  9  
 10  
 11  void MakeChange(Prc,AmtTndrd,QA,DA,NA,CA)
 12     int Prc,AmtTndrd,*QA,*DA,*NA,*CA;
 13  
 14  
 15  {  Prc = AmtTndrd - Prc;
 16     *QA = Prc / 25;
 17     Prc %= 25;
 18     *DA = Prc / 10;
 19     Prc %= 10;
 20     *NA = Prc / 5;
 21     Prc %= 5;
 22     *CA = Prc;
 23  }
 24  
 25  
 26  void PrntDenom(DnmNmPtr,NCoins)
 27     char *DnmNmPtr;  int NCoins;
 28  
 29  {  if (NCoins == 0) return;
 30     printf("%d %s",NCoins,DnmNmPtr);
 31     if (NCoins > 1) printf("s");
 32     printf("  ");
 33  }
 34  
 35  
 36  main()
 37  
 38  {  while(1)  {
 39        printf("enter price, amount tendered\n");
 40        scanf("%d%d",&Price,&AmountTendered);
 41        MakeChange(Price,AmountTendered,&Quarters,&Dimes,&Nickels,&Cents);
 42        if (Price == AmountTendered)
 43           printf("thanks for using exact change\n");
 44        else  {
 45           printf("your change is:  ");
 46           PrntDenom(DenomNamePtr[0],Quarters);
 47           PrntDenom(DenomNamePtr[1],Dimes);
 48           PrntDenom(DenomNamePtr[2],Nickels);
 49           PrntDenom(DenomNamePtr[3],Cents);
 50           printf("\n");
 51        }
 52     }
 53  }
 54  
 55  
 56  heather% gdb a.out
 57  GDB is free software and you are welcome to distribute copies of it
 58   under certain conditions; type "info copying" to see the conditions.
 59  There is absolutely no warranty for GDB; type "info warranty" for details.
 60  GDB 4.1, Copyright 1991 Free Software Foundation, Inc...
 61  (gdb) b 39
 62  Breakpoint 1 at 0x2414: file MakeChange.c, line 39.
 63  (gdb) r
 64  Starting program: /1/home/matloff/Courses/40/Progs/a.out 
 65  enter price, amount tendered
 66  73 100
 67  
 68  Breakpoint 1, main () at MakeChange.c:39
 69  39            MakeChange(Price,AmountTendered,&Quarters,&Dimes,&Nickels,&Cents);
 70  (gdb) p Price
 71  $1 = 73
 72  (gdb) s
 73  MakeChange (Prc=73, AmtTndrd=100, QA=0x4164, DA=0x4160, NA=0x4158, CA=0x415c)
 74      at MakeChange.c:13
 75  13      {  Prc = AmtTndrd - Prc;
 76  (gdb) p Prc
 77  $2 = 73
 78  (gdb) n
 79  14         *QA = Prc / 25;
 80  (gdb) p Prc
 81  $3 = 27
 82  (gdb) p Price
 83  $4 = 73
 84  (gdb) n
 85  15         Prc %= 25;
 86  (gdb) p QA
 87  $5 = (int *) 0x4164
 88  (gdb) p *0x4164
 89  $6 = 1
 90  (gdb) p Quarters
 91  $7 = 1
 92  (gdb) c
 93  Continuing.
 94  your change is:  1 quarter  2 cents  
 95  enter price, amount tendered
 96  ^C
 97  Program received signal 2, Interrupt
 98  0xf7737194 in read ()
 99  (gdb) qy
100  heather% e
101  heather% 
102  script done on Thu Apr 30 12:46:47 1992
\end{verbatim}

\section{Analysis}

\bfs{Overview:}  The function is in Lines 11-23.  Then starting on Line 38, 
we have a test program to try out the function.

\bfs{Line 8:}  Same ingredients as we have seen before, but in more
complicated packages.  First, let's look at

\begin{verbatim}
char *DenomNamePtr[4]
\end{verbatim}

We are declaring a variable named DenomName; what is its type?  Well,
the `[4]' tells us that it is an array, of four elements.  What is the
type of each element?  Well, the `char *' tells us that the type of
each element is pointer-to-character.  In other words, DenomName is
an array of four pointer-to-character variables.

Now, what about the rest of this same line?

\begin{verbatim}
= {"quarter","dime","nickel","cent"};
\end{verbatim}

Recall that we can initialize variables at the same time we declare them.
E.g.

\begin{verbatim}
int Z = 4;
\end{verbatim}

declares a variable Z of integer type, and {\it also} initializes Z to 4.

Similarly, our declaration on Line 8 here initializes DenomNamePtr[0]
to point to the string ``quarter'', DenomNamePtr[1] to point to
``dime'', and so on.

\bfs{Lines 11-23:}  When the `/' operator is applied to an integer
dividend and an integer divisor, `/' produces an integer quotient,
in the same way as \bfs{div} does in Pascal.  `\%' is identical to
Pascal's \bfs{mod}.

\bfs{Lines 56:}  Here I am again using \bfs{gdb} for NON-debugging 
purposes, i.e. just to illustrate in more detail how the pointers work.

\bfs{Lines 69ff:}  Here we are about to call the function.  We have already
read in Price as 73 (Line 66, confirmed on Lines 70-71), and AmountTendered
as 100.  On Line 72, I go ahead; note that I am using the `s' command,
not `n', because I do wish to see what happens line-by-line as I execute
the MakeChange function.

\bfs{Line 73:}  \bfs{gdb} provides me yet another convenience, telling
me all the parameter values, e.g. Prc = 73.  Of course, this is no
surprise, since we already knew that Prc's actual parameter here, Price,
has the value 73.

\bfs{Lines 76-77:}  Just checking once more; Prc is 73.

\bfs{Lines 80ff:}  At this point we have just finished executing

\begin{verbatim}
Prc = AmtTndrd - Prc;
\end{verbatim}

from Line 75 (remember, at Line 75 we were {\it ready} to execute this
statement, but had not yet done so; our `n' command on Line 78 made us
execute this statement).  Note (Lines 80-81) that Prc has now changed
from 73 to 27, as expected (27 = 100 - 73).  \underline{However}, Price
has \underline{not} changed; it is still 73 (Lines 82-83).  Price was
the actual parameter corresponding to the formal parameter Prc, but
since it is call-by-value, the change in Prc did \underline{not} cause
a change in Price.

\bfs{Lines 84ff:}  On Line 84, our typing `n' makes the statement

\begin{verbatim}
*QA = Prc / 25;
\end{verbatim}

from Line 79 execute.  Now on Lines 86-91 we see the result:  The expression
Prc/25 is 27/25, which is 1.  Where will this 1 be put?  Well, the
statement told us to put the 1 in the object pointed to by QA, i.e. the
object at memory location 4164.  But where did this 4164 come from?  Well,
it came from the actual parameter corresponding to the formal parameter QA,
which we can see from Line 69 was \&Quarters, i.e. the address of the
variable Quarters.  Putting all this information together, we see that
the statement

\begin{verbatim}
*QA = Prc / 25;
\end{verbatim}

will place 1 into Quarters!  This is confirmed, on Lines 90-91.  

Of course, this is exactly what we wanted---we did want Quarters to change.
In Pascal we would have made this call-by-reference; C uses only call-by-value,
but that is no problem, since the ``value'' which we pass to the function is
the address of the variable which we want to be changed, in this case the
address of Quarters (which is why I gave the formal parameter the name QA).

\end{document}


