Functions
Goals
This laboratory exercise provides initial practice with functions and passing values as parameters within C programs. In many cases, the code you are given or asked to write will cause errors. This is done intentionally!
HINT: turn statements that are correct into comments rather than deleting them. That makes it easier to restore the program when you are done experimenting.
void and non-void Functions
Read the directions carefully; sometimes you are asked to predict what will go wrong and then test it. Sometimes, you are encouraged to fix it. Use comments to temporarily change code rather than deleting.
-
Copy
quadratic.cto your account, compile and run it, and review the code to determine how it works. Note that there are special instructions for compiling this program, you can find the instructions in the comments at the top of the file. In summary, this file requires linking the math library during compilation, by using the flag-lm. You can read more on our page on Makefiles under the section on linking.-
Procedure
printEquationhas avoidreturn type. Parameters are passed intoprintEquation, but nothing is passed back. What will happen if the statement
is inserted at the end of this procedure?return coeff2 + coeff1 + coeff0; - Verify your prediction by making the modification and compiling the code. Explain the result.
- Restore the program to its original state.
-
Procedure
printEquationis called in both proceduresdisplayExample1anddisplayExample2with just a simple statement, such as:
Predict what will happen if you try to assign the result ofprintEquation (1.0, -3.0, 2.0);printEquationto a variable, such as
After making your prediction, verify whether you were correct by making the change and compiling the code. Explain the results.double value = printEquation(1.0, -3.0, 2.0); - Restore the program again to its original state.
- Procedure
computeDiscriminantreturns adouble. Sometimes beginning coders separate the call to a function with the assignment of the return value. Here are two examples:Attempt 1:
double discriminant; computeDiscriminant (a, b, c);Attempt 2:
computeDiscriminant (a, b, c); double discriminant;Try each of these attempts within procedure
printRoots.- Does the code compile?
- Does the code give the desired result?
-
Change the body of
computeDiscriminantto the following
Compile and run the program.printf ("r = %lf, s = %lf, t = %lf\n", r, s, t); return sqrt (s * s - 4 * r * t);- Describe what is printed by the overall program. What might you conclude about what happens when printing is done in the middle of a computation? For example, how does this impact the overall program's output?
-
Can you identify any guidelines regarding the advisability
of including print statements in functions designed for
computation (e.g.,
computeDiscriminant)? -
In addition to the
printfstatement in functioncomputeDiscriminant, insert the Attempt 1 code from Step 1.6 (intoprintRoots). What happens when procedure with a return value (e.g.,computeDiscriminant) is called on a line by itself?
-
Procedure
Writing Numeric Functions
-
Within a C program, define and use the following functions:
-
Function
circumthat takes a circle's radius as parameter and returns the circumferences of the circle. -
Function
areathat takes a radius as parameter and returns the area of the circle with that radius.
Note: If you'd like to use a more precise value of
π, you can includemath.h, and then referenceM_PI. Read more about mathematical constants inmath.hhere.Note 2: Don't forget that every function (besides main) should include documentation which includes preconditions and postconditons.
-
Function
The Perils of Global Variables
Global variables are variables declared outside any particular function. In terms of our stack model of computation, they exist in a separate part of memory called the static region, which you can draw in your diagrams as a collection of variable-value pairs separate from the stack. They tend to be problematic and are generally to be avoided. Instead, you should favor explicitly passing data between function calls using parameters and return values.
-
To better understand the confusions global variables can cause, consider the
following program.
#include <stdio.h> int glob = 10; void g (void) { // Point (B)---first call to g() for (int i = 0; i < glob; i++) { printf("%d ", i); } printf("\n"); glob += 1; // Point (C)---final call to g() } // g int f (void) { for (int i = 0; i < glob; i += 2) { // Point (A)---first iteration of the for-loop g(); printf("===\n"); } return glob; } // f int main (void) { int ret = f(); // Point (D) } // main- Predict what the program will print.
- Verify your prediction by compiling and running the code. If your prediction was incorrect, trace the execution of the program by recording and updating the stack (including the static region) diagram as you trace the code's execution.
Values as Parameters
Program yoyo.c uses the
function yoyo to simulate a yoyo motion. For this problem, let's define a yoyo movement as a command to move forward and then backward the same amount.
-
Copy
yoyo.cto your account, compile and run it, and review to code to determine how it works.-
Explain what the program does.
- What movements does the program command? Why?
- What output is printed? Why?
-
In the main program, duplicate the line
result = yoyo (repetitions);(I.e., this line should appear twice in succession.)
Does making this call twice change how many times the program commands a yoyo movement in each call? Why or why not?
-
In the main program, replace the line
byresult = yoyo (repetitions);
Does making this call twice change how many times the program commands a yoyo movement in each call? Why or why not?repetitions = yoyo (repetitions); repetitions = yoyo (repetitions); -
In C (as in Scheme), variables declared within a function are separate from variables declared elsewhere (e.g., in
main). In the original program, change the name of therepetitionsvariable torepsthroughout themain procedure. Compile and run the program.Does changing
yoyo's variablerepshave any impact on the variablerepsin themainprocedure? -
Again, return to the original program. This time nest the
call to
yoyoin themainprocedure. That is, the call toyoyowill become:yoyo (yoyo (repetitions));- Make a prediction of what will happen with the above nested call.
- Test out your nested call and explain what happened.
-
Explain what the program does.
-
Recall the
reading's discussion of
memory diagrams. Draw a sequence of stack diagrams for
program
quadratic.cfrom Step 1.Important: To benefit from this exercise, you must actually draw these diagrams. It is not a mental exercise.
-
Consider the program
value-params.c.- Copy the program to your account, compile, and run it.
-
Draw stack diagrams for the program state when
each
printstatement is executed. Be sure you can explain the running of the program at each step, based upon this series of diagrams.