Returning Multiple Values (Advanced) |
Top Previous Next |
An "address" operator can be used to return more than one value from a function. Values can always be returned by passing them through global variables, but a better way in some cases is to return them using pointers. For example:
code ChOut=8, CrLf=9, IntOut=11; int Frog, Pig(11); int Low1, High1, Low2, High2, I;
proc MinMax(Array, Size, Min, Max); \Returns the minimum and maximum values of the array int Array, Size, Min, Max; int I; begin Min(0):= Array(0); Max(0):= Array(0); for I:= 1, Size-1 do begin if Array(I) < Min(0) then Min(0):= Array(I); if Array(I) > Max(0) then Max(0):= Array(I); end; end; \MinMax
begin \Main Frog:= [16, 23, 127, -33, 0]; MinMax(Frog, 5, addr High1, addr Low1); for I:= 0, 10 do Pig(I):= 2*I*I - 16*I + 20; MinMax(Pig, 11, addr High2, addr Low2); IntOut(0, High1); ChOut(0, $09); IntOut(0, Low1); CrLf(0); IntOut(0, High2); ChOut(0, $09); IntOut(0, Low2); CrLf(0); end; \Main
This program displays the following:
-33 127 -12 60
The program displays the minimum and maximum values for two arrays. The calls to MinMax pass the addresses of the High and Low variables, which get values returned to them. The MinMax procedure uses a zero subscript with Min and Max to access the original variables in the calling routine. Compare this to the normal way arguments are passed, where only the value in a variable is passed to a procedure and the procedure does not have access to the variable.
Here is another example of using the address operator to pass values to and from a procedure, this time using reals. This is tricky since the address of a real variable is a 2-byte integer. Three dummy integers (the 0's) are passed along with the address to fill out an 8-byte real (AX). Actually these 0's are not needed here; they are only needed when another argument follows the address argument.
code CrLf=9; code real RlOut=48, Sqrt=53, ATan2=57;
proc Rect2Polar(X,Y,A,D); \Return polar coordinates real X,Y,A,D; begin A(0):= ATan2(Y,X); D(0):= Sqrt(X*X+Y*Y); end; \Rect2Polar
real Ang, Dist; begin Rect2Polar(4.0, 3.0, @Ang, @Dist); RlOut(0, Ang); RlOut(0, Dist); CrLf(0); end;
Note the use of "@" instead of "addr". The "addr" operator doesn't quite work in this situation because it returns an integer address, and what we need here are pointers to the real variables Ang and Dist. A real pointer is a 32-bit address, but it's packaged in a 64-bit value so it can be handled like a real. It's actually just a 32-bit integer with three more zero integers tacked on. The "@" works exactly the same way as "addr" on integer variables, but it returns a real pointer when used on real variables.
When the above program runs, it displays (angle in radians):
0.64350 5.00000 |