(* func)(fred, bert)

Wayne Throop throopw at sheol.UUCP
Fri Nov 17 05:45:43 AEST 1989


> darcy at bbm.UUCP (D'Arcy Cain)
> I don't think it is "lying" to your compiler to 
> [.. declare main an void ..].  It is simply
> declaring your exact intention of what you plan to do in main.

I call declaring main an void "lying to your compiler" because in most
environments you are perforce (or at least perprobably) going to be
linking with a module that has declared it an int (eg: crt0 from many
implementation of the C startup code).  C does not oblige the subroutine
linkages to work properly in this case.  The usage is, therefore,
very unportable.

> tanner at cdis-1.uucp (Dr. T. Andrews)
> It was noted that no return linkage is executed, account of call to
> exit(2) or local equiv.
(But note for ensuing discussion that the incoming linkage WAS executed.)

> I should like to hear details of a case where the code will not
> work.  It seems ridiculous to declare un-portable the results of a
> void-vs-int return linkage which is never made, and I should like
> to hear of an implementation where this actually fails.
> If no real-world example is available, I should be almost as
> satisfied with a conjectural example (clearly marked as conjecture).

I can't supply a real world example complete with C implementations
which display the flaw.  But there are real-world architectures which
would be predisposed to display the flaw, and could very well do so.
They tend not to because either there isn't a C implementation for
them, or the C implementation goes to extreme lengths to emulate a VAX,
thus sidestepping such issues at the cost of performance.

Consider a registerless CISC architecture, with architectural
call-by-reference primitives.  (This architecture actually existed, and
a C system was contemplated for it.) The normal way to "return" a value
was to pass a "hidden" actual temporary by reference to the routine. 
The normal position of this "hidden" actual was argument "0", before the
apparent actuals, bumping all the actuals by 1 stack position.  Applying
this to C's main routine, if it were declared void, all the argument
positions would be off by one, and any attempts to get at the argument
list would give unpredictable results.

Further, consider that exit(2) might well be implemented in such a way
as to have to attempt to clean up the stack in more detail than is
common in many UNIX systems.  For example, it may have to attempt to
clean away architectural error handlers interwoven with call-return
linkages (eg: in order to suppress integer faults for unsigned
arithmetic).  Having the return linkages munged up could well be as
disasterous to exit(2) as it is to return. 

There are more failure scenarios, but two should suffice.

Now, obviously there are ways around these problems that allow C
programmers to lie to the compiler.  But the point is that C
implementors are not obligated to employ them by either the letter of
any standard, or by the spirit of existing practice.  Especially when it
would cost performance. 

> It seems odd that X3J11 or its members would come up with such claims
> about main().  It would seem to fly in the face of years of established
> practice of using exit(condition) as a way to terminate programs.

But years of established practice, going back into the mists of the
time before there ever WAS a void type, make "main" an int-returning
routine.  To declare it otherwise is other than wise.

> Declaring such programs non-portable does not seem to me to be a
> productive use of X3J11's time; obviously, I can use a little bit of
> education from someone who knows better than myself.

No, this is backwards.  Declaring such programs *portable* is a waste
of X3J11's time, because it isn't done as established practice, and
there is no particular reason to tie implementors' hands in this way.
--
Wayne Throop <backbone>!mcnc!rti!sheol!throopw or sheol!throopw at rti.rti.org



More information about the Comp.lang.c mailing list