Functions and Pointer Parameters
Finding the Perimeter and Area of a Rectangle
In the previous lab, you were asked to
write two functions related to circles: one computed the
circumference given the radius, and the second computed the area
given the radius. Following the same approach, program
perim-area-1.c
computes the perimeter and area of a rectangle, given the lengths of
the two sides.
-
Copy
perim-area-1.cto your account. Compile and run it, and review how the program works.-
Following the approach of
the previous lab, draw a
schematic diagram of main memory after the
function
calculate_perimeterhas been called; and draw a second schematic diagram of main memory after the functioncalculate_areahas been called. -
In C, the address operator (
&) allows one to determine the location or address in main memory where a variable is located. Make the following insertions intoperim-area-1.c:Insert into
calculate_perimeterjust before thereturnstatement:printf("parameter side1: location: %lu, value: %lf\n", (unsigned long)&side1, side1); printf("parameter side2: location: %lu, value: %lf\n", (unsigned long)&side2, side2); printf("local lengthPlusWidth: location: %lu, lengthPlusWidth: %lf\n", (unsigned long)&lengthPlusWidth, lengthPlusWidth);Insert into
calculate_areajust before thereturnstatement:printf("parameter side1: location: %lu, value: %lf\n", (unsigned long)&side1, side1); printf("parameter side2: location: %lu, value: %lf\n", (unsigned long)&side2, side2);Insert into
mainjust before thereturnstatement:printf("variable length: location: %lu, value: %lf\n", (unsigned long)&length, length); printf("variable width: location: %lu, value: %lf\n", (unsigned long)&width, width); printf("variable perim: location: %lu, value: %lf\n", (unsigned long)&perimeter, perimeter); printf("variable area: location: %lu, value: %lf\n", (unsigned long)&area, area);Note: In this code, format
%luprints a long decimal integer, but ignores any initial minus sign. (We will talk more about signed and unsigned integers later in the course, when we study the representation of different types of data within a computer.) To avoid compiler warnings about passing adouble *when theprintfformat'%lu'expects anunsigned long, we explicitly make the cast to the appropriate type.Recompile and run your program. To interpret the output, suppose that the first
printfstatement in thecalculate_perimeterfunction produced the output:parameter side1: location: 28580, value: 5.00000
This indicates that the parameter
side1corresponds to memory location 28580, and the value 5.0 is stored there. This part of the schematic diagram might look like:
Use the address information from the inserted print statements to annotate the schematic diagrams from Step 1a with the actual locations or addresses where each parameter and variable was stored.
-
Following the approach of
the previous lab, draw a
schematic diagram of main memory after the
function
Program perim-area-1.c
computed perimeter and area in two functions, because each function can only
return one value. To obtain more than one result from a function, we have to
change the nature of the parameters. This is illustrated
in perim-area-2.c
Passing Values and Addresses as Parameters
Be sure you have completed the reading on passing values and addresses as parameters before continuing with this lab!
-
Copy
perim-area-2.c, compile and run it, and check that it produces exactly the same output asperim-area.1.cTo understand how
perim-area-2.cworks, several print statements have been added to yield programperim-area-2a.c. Compile and run this program.When the program was run on one machine, the program generated the following output:
working with a rectangle of width 7.000000 and length 5.000000 compute: addresses, values, and pointer references side1: address: 640370600, value: 5.000000 side2: address: 640370592, value: 7.000000 lengthPlusWidth: address: 640370616, value: 12.000000 pPerimeter: address: 640370584, value: 640370664, *perimiter: 24.000000 pArea: address: 640370576, value: 640370656, *area: 35.000000 the rectangle's perimeter is 24.000000 the rectangle's area is 35.000000 main: variable addresses and values length: address: 640370680, value: 5.000000 width: address: 640370672, value: 7.000000 perimeter: address: 640370664, value: 24.000000 area: address: 640370656, value: 35.000000This information gives rise to the following schematic for main memory that would have been encountered immediately before the
computeprocedure finished.
As we shall discover later in the course, each
doublerequires 8 units (technically called bytes) of memory, so many of the locations given are 8 numbers apart.-
Explain why the values stored in main memory
for
side1andside2duplicate the numbers stored in main memory forlengthandwidth, respectively. -
The
printfstatement involvingpPerimeterincomputeindicates-
the address of
perimeter(i.e.,&pPerimeter) is 640370584; that is the variablepPerimeteris stored at location 640370584 -
the value stored for
pPerimeteris 640370664; note that this is the location of theperimvariable inmain -
the value referenced by the location stored
in
pPerimeter(i.e., the value stored inperimeter) is 24.00000.
area. -
the address of
-
Explain why the values stored in main memory
for
-
In the previous lab, you wrote two
functions that computed the circumference and the area of a
circle. Write a new version of your solution, so that the
program has just one procedure
compute_circle_geometrythat has three parameters, the radius of a circle, the circumference, and the area.compute_circle_geometryhas avoidreturn type, but takes the radius as input and returns the circumference and area as changed parameters. (You will need to pass in the addresses of the circumference and area variables from yourmainprocedure.) -
Copy the program
pointers-1.cto your account.- Examine the program to gain an initial understanding of what you expect it to produce.
- Compile and run this program. Explain each value printed.
-
Draw a schematic memory diagram, showing variables and their values just
before
pointersFunctionOnefinishes and returns.
-
Copy the program
pointers-2.cto your account.- Examine the program to gain an initial understanding of what you expect it to produce.
- Compile and run the program. Explain each value printed.
-
Draw a schematic memory diagram, showing variables and their
values just before
pointersFunctionTwofinishes and returns. -
Add the declaration
int w = 100;as the first statement in themainprocedure (before the declarationint x = 3;). Recompile and rerun your program. Does the output change? Explain. Does the result depend upon the value assigned tow? Why or why not? -
Add the declaration
int z = 25;immediately after the declaration ofyinmain. Recompile and rerun. Again, does the output change? Why or why not?
-
Copy the program
pointers-3.cto your account.- Examine the program to gain an initial understanding of what you expect it to produce.
- Compile and run this program. Explain each value printed.
-
Draw a schematic memory diagram, showing variables and their values just
before
pointersFunctionThreeInnerfinishes and returns.
For those with extra time
Setting a Max
Write the function
void set_max(int n, int m, int* p_max);
that sets the variable pointed to by p_max to the
larger of n and m.
Dividing the time
Write the function
void split_time(unsigned long total_seconds, unsigned int* p_hours,
unsigned int* p_minutes, unsigned int* p_seconds);
where total_seconds is a time represented as the number of
seconds since midnight. The other paramters are pointers to variables
in which the function will store the equivalent time in hours (0-23),
minutes (0-59) and seconds (0-59), respectively.
