# Proper Way to Pass Numerical Values to a Function

M

#### Martin McCormick

Most of the C programming I write manipulates strings so I haven't had
much experience with numerical functions and passing variables in and
out which brings me to a laughably simple problem that I am having.
How does one pass two unsigned longs in to a function that
will ultimately do floating point calculations on them?

A C tutorial I have says that one should not declare the
inputs to a function as floats but should use doubles which will
handle other numerical types. An example of what I am trying to do is:

void do_percent (lownum, highnum)
double lownum;
double highnum;
{ /*percentage routine*/
printf ("%.3f\n", (lownum/highnum));
return;
} /*percentage routine*/

There is no percentage arithmetic in it yet because if I call
it like:

do_percent (smallnumber, largenumber); with both the input arguments
being unsigned long numbers, the two values become corrupt when doing a
gdb trace.

If I declare them as unsigned longs in the function, they do
keep their values, but printf outputs garbage values so it obviously
doesn't know what I tried to do.

I simply want to learn good practices for passing numerical
values in to functions so any good ideas are appreciated. I have
obviously misunderstood what I read. Many thanks.

E

#### Eric Sosman

Martin said:
Most of the C programming I write manipulates strings so I haven't had
much experience with numerical functions and passing variables in and
out which brings me to a laughably simple problem that I am having.
How does one pass two unsigned longs in to a function that
will ultimately do floating point calculations on them?

A C tutorial I have says that one should not declare the
inputs to a function as floats but should use doubles which will
handle other numerical types. An example of what I am trying to do is:

void do_percent (lownum, highnum)
double lownum;
double highnum;
{ /*percentage routine*/
printf ("%.3f\n", (lownum/highnum));
return;
} /*percentage routine*/

There is no percentage arithmetic in it yet because if I call
it like:

do_percent (smallnumber, largenumber); with both the input arguments
being unsigned long numbers, the two values become corrupt when doing a
gdb trace.

That's because do_percent() expects to receive two
`double' values, but you've passed it two `unsigned long'
and you handed him a codfish; is it any surprise that you're
in trouble? Write

do_percent( (double)smallnumber, (double)largenumber );

A far better solution is to get a more recent tutorial,
one that's been written less than a decade and a half ago.
Then you'd learn that the way you've written the function is
old-hat, and that a newer and better way has been available
since 1989:

void do_percent(double lownum, double highnum)
{
printf ("%.3f", lownum / highnum);
}

This do_percent() function, like the original, requires two
`double' arguments. However, this manner of defining the
function also "advertises" the number and nature of its
arguments so the compiler can generate whatever conversions
are necessary between what you supply and what do_percent()
expects (or can complain if what you supply can't be converted
to `double').

came into the language at the same time as the newer function
style), it should tell you that the old style shown above is
kept around only for compatibility with pre-1989 C and that
you should use the new style for practically all new code.
Look up the word "prototype" in the index -- and if it's not
there, get yourself a newer tutorial.

M

#### Martin McCormick

A far better solution is to get a more recent tutorial,
one that's been written less than a decade and a half ago.
Then you'd learn that the way you've written the function is
old-hat, and that a newer and better way has been available
since 1989:

You are absolutely right. I got to thinking and I have had
that book for eleven years. My thanks to you and to another person
who emailed me off-list with similar information.

I new this might be one of those teachable moments and it
turns out to be. My old book does have prototyping in it and I have
certainly used it before, but I never understood nearly as clearly as
I do now why you have to do it. I have written a lot of code that
works but doesn't have prototyping in it. The only reason that is
true is because I was lucky in that whatever I was doing involved
integers or other variable types that defaulted to the correct type.

It is kind of like having a bare wire in an electrical cord.
Kids, don't try this at home, but one of the two wires in a power cord
is neutral and will probably not shock you if you touch it while in a
tub of bath water. You've got a 50% chance of getting that one or the
hot wire. Good luck.

In all seriousness, my knowledge of C has many holes in it,
but at least now I know what prototyping actually does for one. It
lays down the rules for how data are handled at any given time.

Again, many thanks to both of you.