) Seaman) (01/01/88)
I have been following the discussion of the return vs. exit
controversy, and have a couple of observations:
1) If exit is perferred over return, the why does everyone agree
that crt0 calls main, and then calls exit? Whether it checks
the return value from main is not my question. The point is
crt0 assumes that main will return control to it under normal
circumstances.
2) I work on an AT&T 3B15, an IBM PC (Turbo C and Microsoft C 5.0),
and an Amiga 1000 (Manx 3.4a). All these environments *expect*
main to return to crt0. Of course, if you want to return a
non-zero value to your operating system, you should use exit.
*But*, if a program exits normally, it should be returning zero,
and none of the implementations I've seen discussed here would
prevent that when using return (from main).
3) On the AT&T 3B15, if I write code that *does not* use return
from main as the logical end of the function (meaning, when
all goes well), but uses exit instead, lint complains that I
am returning a random value to the calling environment.
--
Chris Seaman | o\ /o
crs@cpsc6a.att.com <or> | || See "Attack of the Killer Smiley"!
..!ihnp4!cpsc6a!crs | \vvvvvv/ Coming Soon to a newsgroup near you!
| \____/
chip@ateng.UUCP (Chip Salzenberg) (01/04/88)
In article <441@cpsc6b.cpsc6a.att.com> crs@cpsc6b.cpsc6a.att.com (Chris (Batches? We don't need no steenking batches!) Seaman) writes: > 1) If exit is perferred over return, the why does everyone agree > that crt0 calls main, and then calls exit? Whether it checks > the return value from main is not my question. The point is > crt0 assumes that main will return control to it under normal > circumstances. Consider that a function parameter, left undeclared, defaults to type "int". Does this mean that the compiler "expects" you to leave integer function parameters undeclared? Of course not. It is legal to return from main(), but it is neither required nor encouraged. > 3) On the AT&T 3B15, if I write code that *does not* use return > from main as the logical end of the function (meaning, when > all goes well), but uses exit instead, lint complains that I > am returning a random value to the calling environment. You should read the lint manual. Try this: main() { ... /* Time to go home. */ exit(0); /* NOTREACHED */ /* Tell lint that exit() doesn't return. */ } -- Chip Salzenberg UUCP: "{codas,uunet}!ateng!chip" A T Engineering My employer's opinions are a trade secret. "Anything that works is better than anything that doesn't." -- me
marcoz@MARCOZ.BOLTZ.CS.CMU.EDU (Marco Zagha) (03/07/89)
Can anybody explain how returning a structure from a function is typically implemented. Assume it is too big to use registers. Is it returned on the stack? Where does the return structure go in relation to parameters to the function? For a stack that grows downward, is the return value above the parameters, below the parameters, or does the return statement overwrite the parameters? Since I suspect this is implementation dependent, please specify what implementation you are describing. == Marco (marcoz@cs.cmu.edu) P.S. I am *not* writing any code that depends on the implementation. I am just curious. --
dave@motto.UUCP (dave brown) (03/07/89)
In article <4425@pt.cs.cmu.edu> marcoz@MARCOZ.BOLTZ.CS.CMU.EDU.UUCP writes: >Can anybody explain how returning a structure from a function is >typically implemented. Here are two ways that I've seen. The first is in the C compiler for Sys V/68 (Motorola's System V port for the 68000). Any routine that returned a struct has an invisible static area the same size as the struct. The return statement copies the struct value into this area. Code in the calling routine just after the call, copies it to the variable which is to receive it. The second is in the Intermetrics 68000 C compiler. This is a cross- compiler for the 68000, hosted under VAX Ultrix. If a function returns a struct, the compiler inserts a pointer on the stack in front of the first argument. This pointer is the address of the receiving struct variable. The function itself copies the return value through the pointer into the receiving variable. We found out about the second method when a programmer who wasn't using the return value called the function without declaring its return type. His first argument was then taken as the return value address, etc., etc. ----------------------------------------------------------------------------- | David C. Brown | uunet!mnetor!motto!dave | | Motorola Canada, Ltd. | 416-499-1441 ext 3708 | | Communications Division | Disclaimer: Motorola is a very big company | -----------------------------------------------------------------------------
henry@utzoo.uucp (Henry Spencer) (03/08/89)
In article <4425@pt.cs.cmu.edu> marcoz@MARCOZ.BOLTZ.CS.CMU.EDU (Marco Zagha) writes: >Can anybody explain how returning a structure from a function is >typically implemented. Assume it is too big to use registers. >Is it returned on the stack? Where does the return structure >go in relation to parameters to the function? For a stack that >grows downward, is the return value above the parameters, >below the parameters, or does the return statement overwrite >the parameters? The general answer, as you suspected, is "it depends". An additional constraint, tricky to satisfy, is that preferably no dire harm should come about if the function has not been declared properly at the site of the call (i.e. function returns struct but caller is expecting int). C programmers have a nasty tendency to assume that if they're just throwing away the return value, it doesn't matter what type it is. Just about every permutation of putting it on the stack is probably in use in some compiler or other. Probably the best approach, although it's one that requires correct declaration, is to have the caller pass in a pointer (as an invisible extra parameter) to where he wants the return value put. Even stranger approaches have been used in some implementations; the original pdp11 Ritchie compiler allocated a static struct variable for each struct-returning function, and used that as a temporary in the return sequence (yes, this meant that such functions were not completely reentrant). -- The Earth is our mother; | Henry Spencer at U of Toronto Zoology our nine months are up. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
karl@haddock.ima.isc.com (Karl Heuer) (03/08/89)
In article <4425@pt.cs.cmu.edu> marcoz@MARCOZ.BOLTZ.CS.CMU.EDU (Marco Zagha) writes: >Can anybody explain how returning a structure from a function is >typically implemented. Assume it is too big to use registers. Some broken implementations use a static area in the callee and just return its address. This mechanism is not reentrant, is forbidden by the pANS, and will be considered no further in this article. Generally, the caller finds space for the object, and ensures that the callee knows the location of this space. (Small structs are a special case of this, where the caller finds space in the registers, and the callee already knows the location, since it's constant. Note that `location' does not mean `address' in this example.) Usually the second part of this protocol is handled by having the caller pass the address of the struct as a `hidden argument'; this can be done either using the normal argument-passing scheme (so that f(x) generates code that looks like f(&hidden, x)) or any other consistent strategy (some compilers have the caller put the address in a known register, which is not otherwise used in argument passing). The first part of the protocol can be achieved, if necessary, by reserving enough stack space ahead of time, and passing &hidden as if `hidden' were an auto variable. However, since the usual thing to do with a struct-returning function is to store its return value in a struct, the expression `y=f(x)', which would normally generate code resembling `f(&hidden, x); y=x', can often be optimized to `f(&y, x)'. I leave it as an exercise for the student to determine the conditions under which this optimization is legal. >[If it's on the stack,] where does the return structure go in relation to >parameters to the function? It's normal for the arguments to be the last things pushed on the stack, so that they can be cleaned up easily. Thus the space for the return value itself ought to be upward of the args, if the stack grows downward. >Since I suspect this is implementation dependent, please specify >what implementation you are describing. Most of what I've said is pretty generic; read `vax' for a concrete example. I believe it was the 3b20 that used the special register. Btw, the program typedef struct { char junk[8192]; } foo; static foo dummy; foo f() { return dummy; } main() { (void)f(); } can be used to test for a certain compiler bug. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
feg@clyde.ATT.COM (Forrest Gehrke) (03/10/89)
In article <1989Mar7.163952.20063@utzoo.uucp>, henry@utzoo.uucp (Henry Spencer) writes: .> [.....deletes] > Just about every permutation of putting it on the stack is probably > in use in some compiler or other. Probably the best approach, although > it's one that requires correct declaration, is to have the caller pass > in a pointer (as an invisible extra parameter) to where he wants the > return value put. Even stranger approaches have been used in some .> [deletes] I don't understand how a programmer calls a function and passes an "invisible extra parameter". What device does he use to accomplish this? .....Or, are you talking about the compiler programmer? Forrest Gehrke
henry@utzoo.uucp (Henry Spencer) (03/14/89)
In article <42110@clyde.ATT.COM> feg@clyde.ATT.COM (Forrest Gehrke) writes: >> Just about every permutation of putting it on the stack is probably >> in use in some compiler or other. Probably the best approach, although >> it's one that requires correct declaration, is to have the caller pass >> in a pointer (as an invisible extra parameter) to where he wants the >> return value put... > >I don't understand how a programmer calls a function and passes >an "invisible extra parameter". What device does he use to >accomplish this? .....Or, are you talking about the compiler >programmer? The programmer has no say in the matter, any more than he has a say in how a returned struct is put on the stack in an implementation that uses the stack. This is entirely the compiler's job. -- Welcome to Mars! Your | Henry Spencer at U of Toronto Zoology passport and visa, comrade? | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
mdfreed@ziebmef.uucp (Mark Freedman) (03/19/89)
In article <11977@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: >In article <4425@pt.cs.cmu.edu> marcoz@MARCOZ.BOLTZ.CS.CMU.EDU (Marco Zagha) writes: >>Can anybody explain how returning a structure from a function is >>typically implemented. Assume it is too big to use registers. > >Some broken implementations use a static area in the callee and just return >its address. This mechanism is not reentrant, is forbidden by the pANS, and >will be considered no further in this article. > That implies that 1) the MS-DOS implementations with which I'm familiar (Turbo-C 2.0, Datalight C 3.05, Lattice C 3.10), and probably several with which I'm not, are broken 2) the marketeers for these companies have gotten a bit carried away when claiming dpANS compliance. Is anyone aware of MS-DOS compilers which implement structure returns according to dpANS ? Is anyone aware of software companies which intend to correct the broken implementation ?
ark@alice.UUCP (Andrew Koenig) (03/22/89)
> In article <4425@pt.cs.cmu.edu> marcoz@MARCOZ.BOLTZ.CS.CMU.EDU (Marco Zagha) writes: > Some broken implementations use a static area in the callee and just return > its address. This mechanism is not reentrant, is forbidden by the pANS, and > will be considered no further in this article. I can't find the place in my draft ANSI C spec that prohibits this. Can you enlighten me? -- --Andrew Koenig ark@europa.att.com
afscian@violet.waterloo.edu (Anthony Scian) (03/22/89)
In article <1989Mar18.144546.10605@ziebmef.uucp> mdfreed@ziebmef.UUCP (Mark Freedman) writes: >>Some broken implementations use a static area in the callee and just return >>its address. This mechanism is not reentrant, is forbidden by the pANS, and >>will be considered no further in this article. >> > That implies that 1) the MS-DOS implementations with which I'm familiar >(Turbo-C 2.0, Datalight C 3.05, Lattice C 3.10), and probably several with >which I'm not, are broken 2) the marketeers for these companies have >gotten a bit carried away when claiming dpANS compliance. > Is anyone aware of MS-DOS compilers which implement structure returns >according to dpANS ? Is anyone aware of software companies which intend to >correct the broken implementation ? WATCOM C7.0 is one MS-DOS ANSI C compiler that did it right (with the best optimizer, also). By the way, you forgot to include Microsoft's C compiler in your list of broken compilers (even their OS/2 version!). -- Anthony Scian \\ "Working with roots and twigs, Tom managed afscian@violet.uwaterloo.ca \\ to build a working tractor beam. Then he afscian@violet.waterloo.edu \\ waited ..." - Aarrr Trek: The Wrath of Tom