Working with Functions in C: Returning Function Results

The functions in Program 8.4 and 8.5 perform some straightforward calculations and then display the results of the calculations at the terminal. However, you might not always want to have the results of your calculations displayed. The C language provides you with a convenient mechanism whereby the results of a function can be returned to the calling routine. This is not new to you because you’ve used it in all previous pro- grams to return from main. The general syntax of this construct is straightforward enough:

return expression;

This statement indicates that the function is to return the value of expression to the calling routine. Parentheses are placed around expression by some programmers as a matter of programming style, but their use is optional.

An appropriate return statement is not enough. When the function declaration is made, you must also declare the type of value the function returns. This declaration is placed immediately before the function’s name. Each of the previous examples in this book defined the function main to return an integer value, which is why the keyword int is placed directly before the function name. On the other hand, a function declaration that starts like this:

float kmh_to_mph (float km_speed)

begins the definition of a function kmh_to_mph, which takes one float argument called km_speed and which returns a floating-point value. Similarly,

int gcd (int u, int v)

defines a function gcd with integer arguments u and v that returns an integer value. In fact, you can modify Program 8.5 so that the greatest common divisor is not displayed by the function gcd but is instead returned to the main routine, as shown in Program 8.6.

Program 8.6   Finding the Greatest Common Divisor  and Returning  the Results

/* Function to find the greatest common divisor of two nonnegative integer values and to return the result                              */

#include <stdio.h>

int gcd (int u, int v)

{

int temp;

while ( v != 0 ) {

temp = u % v;

u = v;

v = temp;

}

return u;

}

int main (void)

{

int result;

result = gcd (150, 35);

printf (“The gcd of 150 and 35 is %i\n”, result);

result = gcd (1026, 405);

printf (“The gcd of 1026 and 405 is %i\n”, result);

printf (“The gcd of 83 and 240 is %i\n”, gcd (83, 240));

return 0;

}

Program 8.6   Output

The gcd of 150 and 35 is 5

The gcd of 1026 and 405 is 27

The gcd of 83 and 240 is 1

After the value of the greatest common divisor has been calculated by the gcd function, the statement

return u;

is executed. This has the effect of returning the value of u, which is the value of the greatest common divisor, back to the calling routine.

You might be wondering what you can do with the value that is returned to the call- ing routine. As you can see from the main routine, in the first two cases, the value that is returned is stored in the variable result. More precisely, the statement

result = gcd (150, 35);

says to call the function gcd with the arguments 150 and 35 and to store the value that is returned by this function in the variable result.

The result that is returned by a function does not have to be assigned to a variable, as you can see by the last statement in the main routine. In this case, the result returned by the call

gcd (83, 240)

is passed directly to the printf function, where its value is displayed.

A C function can only return a single value in the manner just described. Unlike some other languages, C makes no distinction between subroutines (procedures) and functions. In C, there is only the function, which can optionally return a value. If the declaration of the type returned by a function is omitted, the C compiler assumes that the function returns an int—if it returns a value at all. Some C programmers take advantage of the fact that functions are assumed to return an int by default and omit the return type declaration. This is poor programming practice and should be avoided.

When a function returns a value, make certain you declare the type of value returned in the function’s header, if only for the sake of improving the program’s readability. In this manner, you can always identify from the function header not only the function’s name and the number and type of its arguments, but also if it returns a value and the returned value’s type.

As noted earlier, a function declaration that is preceded by the keyword void explicit- ly informs the compiler that the function does not return a value. A subsequent attempt at using the function in an expression,  as if a value were returned, results in a compiler error message. For example, because the calculateTriangularNumber function of Program 8.4 did not return a value, you placed the keyword void before its name when defining the function. Subsequently attempting to use this function as if it returned a value, as in

number = calculateTriangularNumber (20);

results in a compiler error.

In a sense, the void data type is actually defining the absence of a data type. Therefore, a function declared to be of type void has no value and cannot be used as if it does have a value in an expression.

In Chapter 6, “Making Decisions,” you wrote a program to calculate and display the absolute value of a number. Now, write a function that takes the absolute value of its argument and then returns the result. Instead of using integer values  as you did in Program 6.1, write this function to take a floating value as an argument and to return the answer as type float, as shown in Program 8.7.

Program 8.7   Calculating the Absolute Value

// Function to calculate the absolute value

#include <stdio.h>

float absoluteValue (float x)

{

if ( x < 0 )

x = -x;

return x;

}

int main (void)

{

float f1 = -15.5, f2 = 20.0, f3 = -5.0;

int   i1 = -716;

float result;

result = absoluteValue (f1);

printf (“result = %.2f\n”, result);

printf (“f1 = %.2f\n”, f1);

result = absoluteValue (f2) + absoluteValue (f3);

printf (“result = %.2f\n”, result);

result = absoluteValue ( (float) i1 );

printf (“result = %.2f\n”, result);

result = absoluteValue (i1);

printf (“result = %.2f\n”, result);

printf (“%.2f\n”, absoluteValue (-6.0) / 4 );

return 0;

}

Program 8.7   Output

result = 15.50

f1 = -15.50

result = 25.00

result = 716.00

result = 716.00

1.50

The absoluteValue function is relatively straightforward. The formal parameter called x is tested against zero. If it is less than zero, the value is negated to take its absolute value. The result is then returned back to the calling routine with an appropriate return state- ment.

You should note some interesting points with respect to the main routine that tests out the absoluteValue function. In the first call to the function, the value of the vari- able f1, initially set to –15.5, is passed. Inside the function itself, this value is assigned to the variable x. Because the result of the if test is TRUE, the statement that negates the value of x is executed, thereby setting the value of x to 15.5. In the next statement, the value of x is returned to the main routine where it is assigned to the variable result and is then displayed.

When the value of x is changed inside the absoluteValue function, this in no way affects the value of the variable f1.When f1 was passed to the absoluteValue function, its value was automatically  copied into the formal parameter x by the system. Therefore, any changes made to the value of x inside the function affect only the value of x and not the value of f1. This is verified by the second printf call, which displays the unchanged value of f1 at the terminal. Make certain you understand that it’s not possible for a func- tion to directly change the value of any of its arguments—it can only change copies of them.

The next two calls to the absoluteValue function illustrate how the result returned by a function can be used in an arithmetic expression. The absolute value of f2 is added to the absolute value of f3 and the sum is assigned to the variable result.

The fourth call to the absoluteValue function introduces the notion that the type of argument that is passed to a function should agree with the type of argument as declared inside the function. Because the function absoluteValue expects a floating value as its argument, the integer variable i1 is first cast to type float before the call is made. If you omit the cast operation, the compiler does it for you anyway because it knows the absoluteValue function is expecting a floating argument. (This is verified by the fifth call to the absoluteValue function.) However, it’s clearer what’s going on if you do the casting yourself rather than relying on the system to do the conversion for you.

The final call to the absoluteValue function shows that the rules for evaluation of arithmetic expressions also pertain to values returned by functions. Because the value returned by the absoluteValue function is declared to be of type float, the compiler treats the division operation as the division of a floating-point number by an integer. As you recall, if one operand of a term is of type float, the operation is performed using floating arithmetic. In accordance with this rule, the division of the absolute value of

–6.0 by 4 produces a result of 1.5.

Now that you’ve defined a function that computes the absolute value of a number, you can use it in any future programs in which you might need such a calculation per- formed. In fact, the next program (Program 8.8) is just such an example.

Source: Kochan Stephen G. (2004), Programming in C: A Complete Introduction to the C Programming Language, Sams; Subsequent edition.

Leave a Reply

Your email address will not be published. Required fields are marked *