structure function returns -- how?

Stuart D. Gathman stuart at bms-at.UUCP
Wed Dec 24 12:53:05 AEST 1986


In article <490 at aw.sei.cmu.edu.sei.cmu.edu>, firth at sei.cmu.edu (Robert Firth) writes:

	[ we are discussing returning structures from functions ]

> (a) Registers.  If the structured object is small enough, use the

	Definitely do this is all cases.

> (b) Caller preallocates.  This passes as an extra parameter a pointer
>     to a result area computed by the caller.  Note that this requires

	In most cases this will be object being assigned to.  Only
	when the selection operator is applied to the function result
	will a temp area have to be allocated.  See ultimate solution
	below.

> (c) Function allocates static space and returns pointer.  Caller copies.

	I hate this because it is inefficient; the structure is copied
	twice!  Unfortunately all of the compilers we have do it because
	it is simple for the compiler.  However, some of the objections
	below do not hold water.

>     This is not reentrant, as has been pointed out.  Nor does it work if
>     the function is recursive.  Since reentrancy bugs are very hard to
>     find, as a compiler writer I would absolutely NEVER use this technique.

	It *is* recursive (the static area is only used by the return
	statement - think about it).  It is also reentrant if each process
	has its own static area as it should anyway for anything reasonable
	to happen.  (This is where the const storage class comes in
	handy.  Constants can be shared.  Shared data has to be accessed
	via pointers or else declared via a non-ansi global storage class.)
	This method has problems when the function is called from a signal
	catching function.

>     A variation is for the function to return a pointer to a declared
>     object holding the value.  For example, if the function does a lookup
>     of an external array of struct objects, it can simply return a pointer
>     into the table.

	In fact, it can return a pointer to any class of variable
	including auto - except that signals will bomb when auto is
	handled in this way.  It is
	still recursive and reentrant though and eliminates the
	double copy.  This works because the function result is
	an rvalue and can be assigned or passed on the stack without
	wiping its value on most architectures.

> (d) Allocate on heap

	Boooooo!  Hisss.  You might as well not allow functions
	returning structures; it is that inefficient.

> (e) Function leaves result on stack.

	This works best when done a la pascal.  The caller decrements
	the stack pointer (for descending stacks) to reserve room
	for the result before stacking function arguments.  The
	function does the copy.  Another copy is required if doing
	an assignment, but passing the result to another function
	requires no extra overhead!  (Not even the code in the calling
	sequence to do the copy.)

	Knowledge of the structure size is required at compile time.
	This is re* and immune to interrupts.  It also works with
	signals.

*** The real solution ***

(f)	For an assignment, the caller passes a pointer to the object
	being assigned.  The function does the copy.

	For a function argument (including selection), the stack
	pointer is decremented as in (e) and a pointer to the
	stack area so reserved is passed.  (I.e. save the stack pointer
	in a register, decrement the stack pointer, push the register.)
	Again, the function does the copy.

	This is recursive, reentrant (even without seperate static areas),
	immune to interrupts, works with signals, the result is
	always copied only once, and the code for the copy is in
	the function - not the calling sequence!

	(I hate it when the result is copied twice!  Grrr.)

P.S. 	This idea is free provided that the user implements it
on our compilers or else hires me to implement it on their compiler. :-)
-- 
Stuart D. Gathman	<..!seismo!dgis!bms-at!stuart>



More information about the Comp.lang.c mailing list