32. How Can I Perfect My Functions?

Using Return Values and Prototypes

image

This chapter is not the end of your C learning. This chapter is only the beginning. Sounds deep, doesn’t it? This chapter completes the multiple-function picture by showing you how to return values from the called function to the calling function. Also, function prototypes are explained.

The bottom line is this: You will now understand why most programs in this book contain this line:

return 0;

and you will understand the true purpose of header files.

Returning Values

So far you’ve seen how to send variables to functions. You’re now ready to learn how to return a value. When a function is to return a value, use the return statement to return the value. Often, C programmers put parentheses after the return statement, with the return value inside those parentheses, such as return (answer);.

Note

image

If a function doesn’t return a value, a return statement isn’t needed because the function will return to the calling function automatically. Nevertheless, if you need to return a value, a return statement is required.

Although you can pass several arguments to functions, you can return only one value to the calling function! Figure 32.1 explains what is going on. There are no exceptions to this rule.

Figure 32.1. You can pass more than one value but return only one.

image

Although a single return value might seem limiting, it really is not. Consider the built-in sqrt() function. You might remember from Chapter 20, “Can C Do My Math Homework?”, that sqrt() returns the square root of whatever value is passed to it. sqrt() doesn’t return several values, only one. As a matter of fact, none of the built-in functions returns more than a single value, and neither can yours.

Warning

image

The gets() function seems as if it returns more than one value because it returns a character string array. Remember, though, that an array name is nothing more than a pointer to the array’s first position. Therefore, gets() actually returns a character pointer that points to the beginning of the string entered by the user.

The following program contains a function that receives three integer values: a, b, and c. The function named fMul3() multiplies those three values by each other and then returns the answer.

image

Clue

image

This program uses the long int data type because the three integers might produce a large value when multiplied by each other.

Here is a sample output from this program:

What is the first number to multiply? 3
What is the second number to multiply? 4
What is the third number to multiply? 5

Those three values multiplied by each other equal 60.

Note

image

Notice that main() assigned the fMul3() return value to answer. main() had to do something with the value that was returned from fMul3().

You can put an expression after return as well as variables. This:

sales = quantity * price;
return (sales);

is identical to this:

return (quantity * price);

The Return Data Type

At the beginning of the fMul3() function, you see long int. long int is the data type of the returned value locAnswer. You must put the return data type before any function name that returns a value. If the function returned a float, float would have to precede the function name.

If you don’t specify a return data type, C assumes int. Therefore, C expects that every function without a return data type specified explicitly will return int. Both of these functions’ first lines mean exactly the same thing to C:

int myFun(int a, float x, char c)

and

myFun(int a, float x, char c)  /* int is assumed */

Clue

image

Guess what? Even main() is assumed to return an int value unless you specify an overriding return data type. That is why you’ve seen return 0; at the end of most of these programs! Because main() has no specified return data type, int is assumed, and the return 0; ensures that an int is returned to DOS. DOS, by the way, just ignores the return data type unless you want to use the advanced DOS errorlevel command to receive the 0.

If your function doesn’t return a value or if your function isn’t passed a value, you can insert the keyword void for either the return data type or the parameter list or both. Therefore, the first line of a function that neither gets any value nor returns any value might look like this:

void doSomething(void)  /* Neither is passed nor returns */

One Last Step: Prototype

There is one last step to making a function work properly. If a function returns any value other than int, you should prototype that function. Actually, you should prototype functions that return integers as well.

The word prototype means a model of something else. A prototype of a function is just a model of the actual function. At first, a C prototype seems like a total waste of time.

The reason functions that return int values don’t need prototypes is because int is the default prototyped return value unless you specify a different return value. Therefore, these two prototypes both model the same function:

int aFunc(int x, float y);  /* 2 passed, one integer returned */

and

aFunc(int x, float y);  /* 2 passed, one integer returned */

Note

image

Prototypes aren’t required if you don’t return a value or if you return an integer value, but they are strongly recommended. Once you prototype, C ensures that you don’t pass a float value to a function that expects to receive a char. Without the prototype, C would try to convert the float to a char, and a bad value would be passed as a result.

To prototype a function, place an exact duplicate of the function’s first line somewhere before main(). The prototype for fMul3() appears right before main() in the program you saw earlier. The line is not a function call because it appears before main(). The line is not a function’s actual first line because of the semicolon that follows all prototypes. The line is a function prototype. If your program calls 20 functions, you should have 20 prototypes.

Prototype every function in your programs—every function called by your code and even the built-in functions such as printf(). “Huh?” might be a good question at this point. You might wonder how you can prototype printf() when you didn’t write it to begin with. The file STDIO.H contains a prototype for printf(), scanf(), getchar(), and many other input and output functions! The prototype for strcpy() appears in STRING.H. You should find out the name of the header file when you learn a new builtin function so that you can #include it and make sure that each function is prototyped.

The following program does not work correctly because the float return type is not prototyped correctly. Remember, C assumes that an int is returned (even if you return a different data type) unless you override the return type in the prototype.

image

This shows the incorrect output:

What is the atomic weight? .0125
What is the factor? .98
The net weight is 0.0000

To fix the problem, you have to change the prototype to this:

float compNet(float atomWeight, float factor);

and the compNet()’s definition line (its first line) to match the prototype like this:

float compNet(float atomWeight, float factor)

Wrapping Things Up

Never pass or return a global variable if you use one. Global variables don’t have to be passed. Also, the parameter lists in the calling function, receiving function, and prototype should match in both numbers and data types. (The names of the values don’t have to match.)

You now know everything there is to know about passing parameters and returning values. Put on your official programmer’s thinking cap and start your C compiler!

Rewards

image

• Place the return data type before a function name that returns a value.

• The return value appears after a return statement.

In the calling function, do something with the return value. Print it or assign it to something. Calling a function that returns a value is useless if you do nothing with the return value.

• Use void as the return data type or in the parameter list if you neither return nor pass values to a function.

Pitfalls

image

• Don’t return more than one value from a function.

• Don’t return a noninteger without a prototype. Better yet, prototype all functions except main().

In Review

The goal of this chapter was to round out your knowledge of functions by explaining prototypes and return values. When your program contains lots of functions, prototype those functions somewhere before main(). The prototypes tell C what to expect. After you prototype, you can pass and return variables of any data type. (You can return ints only if you don’t prototype.)

The prototype ensures that you don’t inadvertently pass the wrong data types to functions. For example, if the prototype states that you’ll pass two floats to a function, but you accidentally pass two ints, C will complain. C won’t complain if you don’t prototype, and you might get wrong results because of it.

Now that you know how to return values, you can write functions that mirror those that are built in, such as sqrt() and rand(). When you call a function, that function returns a value based on the function’s code. A function can return a maximum of one value, just like functions that are built in.

Code Example

image

Code Analysis

This program shows how to prototype and call a function that returns one-half the value passed to it. The prototype lets C know that the function named divideIt() receives and returns a floating-point value. Because divideIt()’s local variable can’t be used in main(), its value is returned to main() and captured in main()’s variable named half.

It would be more efficient to divide the value by 2 in main(), but this example better demonstrates the concepts in this chapter. Here is a sample output from the program so you can see how it works:

Please type a number: 45.6
Your number divided by two is 22.8.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.218.215