[comp.std.c] Must main return a value?

walterm@hpwrce.HP.COM (Walter Murray) (06/27/91)

Is the following program strictly conforming?

   int main(void) { return; }

Many people have written that the main function must return a value.
I can't find such a requirement in the Standard.  I have read 2.1.2.2.3
and 3.6.6.4.  Am I missing something?

Walter Murray

michi@ptcburp.ptcbu.oz.au (Michael Henning) (06/28/91)

walterm@hpwrce.HP.COM (Walter Murray) writes:

>Is the following program strictly conforming?

>   int main(void) { return; }

>Many people have written that the main function must return a value.
>I can't find such a requirement in the Standard.  I have read 2.1.2.2.3
>and 3.6.6.4.  Am I missing something?

Section 2.1.2.2.3 (Program termination) is quite explicit:

"A return from the initial call to the main function is equivalent to
calling the exit function with the value returned by the main function as
its argument. If the main function executes a return that specifies no
value, the termination status returned to the host environment is undefined."

Section 3.6.6.4 (The return Statement) says:

"If a return statement without an expression is executed, and the value of
the function call is used by the caller, the behavior is undefined."

Note that for section 3.6.6.4 to apply, there must be a caller, but the
caller in this case is the environment, so 2.1.2.2.3 applies instead.

The upshot is that the program is strictly conforming, but the exit
status the OS gets to see is undefined.

To write truly portable code, it pays to explicitely call exit() since
some (non-conforming) implementations to not return a defined value
to the OS when a return from main is executed (even if that return
specifies a value). So it pays to write

int main(void) { exit(0); }

to be sure. Unfortunately, many versions of lint will complain about
an undefined return value from main in this case, because they do not
know about exit(). If you want to be paranoid, you can write

int main(void)
{
	exit(0);
	return 0;	/* Keep lint happy */
}


						Michi.
-- 
      -m------- Michael Henning			+61 75 950255
    ---mmm----- Pyramid Technology		+61 75 522475 FAX
  -----mmmmm--- Research Park, Bond University	michi@ptcburp.ptcbu.oz.au
-------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA	uunet!munnari!ptcburp.oz!michi

diamond@jit533.swstokyo.dec.com (Norman Diamond) (06/28/91)

In article <7830001@hpwrce.HP.COM> walterm@hpwrce.HP.COM (Walter Murray) writes:
>Is the following program strictly conforming?
>   int main(void) { return; }
>Many people have written that the main function must return a value.
>I can't find such a requirement in the Standard.  I have read 2.1.2.2.3
>and 3.6.6.4.  Am I missing something?

For the effect of the program to be defined, the main function must return
a value.  It does seem strange that the compiler is required to issue a
diagnostic for a return statement with a value in a void function, but not
for the opposite mistake.

OK, if you don't want your program to send a small nuclear device at your car,
the main function must return a value.  (2.1.2.2 neither allows nor disallows
this extreme an effect; 3.6.6.4 allows it.)
--
Norman Diamond       diamond@tkov50.enet.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Permission is granted to feel this signature, but not to look at it.

hooverm@sysjj.mdcbbs.com (SQUID 6 on the DARK side) (06/28/91)

In article <1991Jun28.043342.27540@ptcburp.ptcbu.oz.au>, michi@ptcburp.ptcbu.oz.au (Michael Henning) writes:
> walterm@hpwrce.HP.COM (Walter Murray) writes:
> 
>>Is the following program strictly conforming?
> 
>>   int main(void) { return; }
> 
>>Many people have written that the main function must return a value.
>>I can't find such a requirement in the Standard.  I have read 2.1.2.2.3
>>and 3.6.6.4.  Am I missing something?
>
>...stuff deleted...
>
> some (non-conforming) implementations to not return a defined value
> to the OS when a return from main is executed (even if that return
> specifies a value). So it pays to write
> 
> int main(void) { exit(0); }
> 
> to be sure. Unfortunately, many versions of lint will complain about
> an undefined return value from main in this case, because they do not
> know about exit(). If you want to be paranoid, you can write
> 
> int main(void)
> {
> 	exit(0);
> 	return 0;	/* Keep lint happy */
> }

	I've run into this problem running code on 3 platforms (VMS,SUN & PC)

I use:
	void main()
	{
	insert magic code here
	}

This seems to work well on all three platforms.


			Mark  <o===6

kremer@cs.odu.edu (Lloyd Kremer) (06/28/91)

In article <1991Jun28.043342.27540@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes:
>If you want to be paranoid, you can write
>
>int main(void)
>{
>	exit(0);
>	return 0;	/* Keep lint happy */
>}

int main(void)
{
	exit(0);
	/*NOTREACHED*/	/* Keeps most lints happy without extra code */
}

					Lloyd Kremer
					Hilton Systems, Inc.
					kremer@cs.odu.edu

exspes@gdr.bath.ac.uk (P E Smee) (06/28/91)

In article <7830001@hpwrce.HP.COM> walterm@hpwrce.HP.COM (Walter Murray) writes:
>Is the following program strictly conforming?
>
>   int main(void) { return; }
>
>Many people have written that the main function must return a value.
>I can't find such a requirement in the Standard.  I have read 2.1.2.2.3
>and 3.6.6.4.  Am I missing something?

Yep.  The construct you used, 'int main (...' declares main to be a
function which returns an int.  You have declared it as returning a
value, and then not returned a value of the type specified.  Speaking
pedantically, that's a prima facie violation.

In practice, since return from main() generally throws you out of your
C-program environment, and back into your native operating system
environment, whether or not it makes any difference depends on your
OS.  Many OSes expect progs to return status codes -- especially progs
which have been declared to return status codes.  If you don't return
one, the results will be OS-dependent but can range the full gamut from
unpleasantly surprising to unpleasantly mysterious.

If you're really unlucky, your failure to return the value you promised
won't make any difference at all -- until next year, when you've got to
move the prog to another OS platform and have forgotten what you did.

-- 
Paul Smee, Computing Service, University of Bristol, Bristol BS8 1UD, UK
 P.Smee@bristol.ac.uk - ..!uunet!ukc!bsmail!p.smee - Tel +44 272 303132

steve@taumet.com (Stephen Clamage) (06/28/91)

michi@ptcburp.ptcbu.oz.au (Michael Henning) writes:

>The upshot is that the program is strictly conforming, but the exit
>status the OS gets to see is undefined.

No.  A strictly-conforming program "shall not produce output dependent
on any unspecified, undefined, or implementation-defined behavior"
(section 1.7).

>So it pays to write
>int main(void) { exit(0); }

Except that EXIT_SUCCESS need not have the value 0.  This might be
wrong in an ANSI environment.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

eggert@twinsun.com (Paul Eggert) (06/29/91)

steve@taumet.com (Stephen Clamage) writes:

>michi@ptcburp.ptcbu.oz.au (Michael Henning) writes:
>>So it pays to write
>>int main(void) { exit(0); }

>Except that EXIT_SUCCESS need not have the value 0.  This might be
>wrong in an ANSI environment.

But section 4.10.4.3 says that exit(0) and exit(EXIT_SUCCESS) have the
same effect even if EXIT_SUCCESS!=0.

Anyway, Posix 1003.1-1990 (section 8.1) says that EXIT_SUCCESS==0,
so hosts where EXIT_SUCCESS!=0 are an endangered species.

gwyn@smoke.brl.mil (Doug Gwyn) (06/29/91)

In article <7830001@hpwrce.HP.COM> walterm@hpwrce.HP.COM (Walter Murray) writes:
>Many people have written that the main function must return a value.
>I can't find such a requirement in the Standard.  I have read 2.1.2.2.3
>and 3.6.6.4.  Am I missing something?

You must be -- 2.1.2.2.3 states explicitly "If the main function executes a
return that specifies no value, the termination status returned to the host
environment is undefined."  That meets the condition for causing undefined
behavior on at least two counts.

gwyn@smoke.brl.mil (Doug Gwyn) (06/29/91)

In article <787@taumet.com> steve@taumet.com (Stephen Clamage) writes:
>Except that EXIT_SUCCESS need not have the value 0.  This might be
>wrong in an ANSI environment.

No -- while it is true that EXIT_SUCCESS might be defined as a nonzero value,
a conforming hosted implementation must also support the exit status value 0
as a "separate but equal" way to specify successful termination status.

gwyn@smoke.brl.mil (Doug Gwyn) (06/29/91)

In article <1991Jun28.055840.29919@tkou02.enet.dec.com> diamond@jit533.enet@tkou02.enet.dec.com (Norman Diamond) writes:
>It does seem strange that the compiler is required to issue a diagnostic for
>a return statement with a value in a void function, but not for the opposite
>mistake.

That's because a vast amount of existing, correct (as of when it was written)
C code is like that.  Before there was a "void" type in C, the effect of a
void-valued function was achieved by coding a (default) int-valued function
and not returning a value.  It's easy for an implementation to deal with this
common practice (either by not worrying about loading the result register or
by building a dummy result value before the function exit code), and as a
widespread officially-sanctioned practice (K&R 1st Ed. had examples), there
was no good reason to disallow this usage.  All that X3J11 had to do along
these lines was to note the obvious fact that an attempt to use a value that
the program hadn't bothered to set up would be nonsensical.

gwyn@smoke.brl.mil (Doug Gwyn) (06/29/91)

In article <1991Jun28.072521.1@sysjj.mdcbbs.com> hooverm@sysjj.mdcbbs.com (SQUID 6 on the DARK side) writes:
>I use:
>	void main()
>	{
>	insert magic code here
>	}
>This seems to work well on all three platforms.

Damn it, this is comp.std.c, not comp.lang.c.neophyte.  Walter Murray was
asking a standard-related question; he presumably doesn't care any more
than I do whether or not you have successfully gotten away with violations
of the C standard using a small number of specific implementations.

lmiller@aero.org (Lawrence H. Miller) (06/29/91)

In article <16575@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <7830001@hpwrce.HP.COM> walterm@hpwrce.HP.COM (Walter Murray) writes:
>>Many people have written that the main function must return a value.
>>I can't find such a requirement in the Standard.  I have read 2.1.2.2.3
>>and 3.6.6.4.  Am I missing something?
>
>You must be -- 2.1.2.2.3 states explicitly "If the main function executes a
>return that specifies no value, the termination status returned to the host
>environment is undefined."  That meets the condition for causing undefined
>behavior on at least two counts.


The question one might ask of a standards body is why this is "undefined"
and not "implementation defined," since it clearly involves the program's
interaction with its host.  This is, in fact, alluded to in the description
of the exit() function in 4.10.4.3:

	If the value [returned] is EXIT_SUCCESS...
	If the value [returned] is EXIT_FAILURE...
	Otherwise the status returned is implementation-defined.

-- 
Larry Miller
The Aerospace Corporation
lmiller@aero.org
(213 soon to be 310)336-5597

steve@groucho.ucar.edu (Steve Emmerson) (06/29/91)

In <16577@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:

>In article <787@taumet.com> steve@taumet.com (Stephen Clamage) writes:
>>Except that EXIT_SUCCESS need not have the value 0.  This might be
>>wrong in an ANSI environment.

>No -- while it is true that EXIT_SUCCESS might be defined as a nonzero value,
>a conforming hosted implementation must also support the exit status value 0
>as a "separate but equal" way to specify successful termination status.

In a POSIX environment, at least, EXIT_SUCCESS *is* 0.  Period.

Are there non-POSIX (or pre-POSIX) environments in which EXIT_SUCCESS is
(or was) not zero (I know about VMS)?

Steve Emmerson        steve@unidata.ucar.edu        ...!ncar!unidata!steve

gwyn@smoke.brl.mil (Doug Gwyn) (06/29/91)

In article <1991Jun29.002410.27632@aero.org> lmiller@aero.org (Lawrence H. Miller) writes:
>The question one might ask of a standards body is why this is "undefined"
>and not "implementation defined," since it clearly involves the program's
>interaction with its host.

I don't think you understand what these terms mean as used in the C
standard.  Either that, or you really believe that an implementation
could document what would happen for every program that returned
garbage instead of a deliberate value, where the garbage is NOT
specified in the program (unlike the case for the part of 4.10.4.3
that you quoted).

Basically, this was specified to cause undefined behavior because
that's exactly what it does.

lmiller@aero.org (Lawrence H. Miller) (06/30/91)

In article <16582@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <1991Jun29.002410.27632@aero.org> lmiller@aero.org (Lawrence H. Miller) writes:
>>The question one might ask of a standards body is why this is "undefined"
>>and not "implementation defined," since it clearly involves the program's
>>interaction with its host.
>
>I don't think you understand what these terms mean as used in the C
>standard.  Either that, or you really believe that an implementation
>could document what would happen for every program that returned
>garbage instead of a deliberate value, where the garbage is NOT
>specified in the program (unlike the case for the part of 4.10.4.3
>that you quoted).
>
>Basically, this was specified to cause undefined behavior because
>that's exactly what it does.

	I understand fully well what the terms "undefined" and
	"implementation defined" mean.  I don't understand what the
	term "garbage" means and can't find it defined anywhere in the
	standard.


-- 
Larry Miller
The Aerospace Corporation
lmiller@aero.org
(213 soon to be 310)336-5597

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (06/30/91)

In article <16582@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
> Either that, or you really believe that an implementation
> could document what would happen for every program that returned
> garbage instead of a deliberate value, where the garbage is NOT
> specified in the program (unlike the case for the part of 4.10.4.3
> that you quoted).

I really believe that an implementation could document what would happen
for every program that returned garbage instead of a deliberate value.
At most it would take a special case in the compiler: ``Oh, a void
return inside main? Let's make that return 0.'' Then the documentation
would reflect this.

> Basically, this was specified to cause undefined behavior because
> that's exactly what it does.

That's what it does in historical implementations, but ANSI tightened up
on a lot of minor points, and they could easily have taken care of this
one. I'm not saying this is necessarily a good idea, but you can't just
throw out the question. Why would it have been bad to insist on
implementation-defined behavior? *Why* is undefined a better idea?
``That's exactly what it does'' is not an excuse; if you took that
logic, it would be undefined whether static variables are initialized to
0, undefined whether unions of structs beginning with the same type in
fact overlapped, and undefined whether int a[n]; a + n is always valid.

---Dan

gwyn@smoke.brl.mil (Doug Gwyn) (06/30/91)

In article <12049.Jun2922.08.1391@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>> Basically, this was specified to cause undefined behavior because
>> that's exactly what it does.
>That's what it does in historical implementations, but ...

Ok, this really isn't worthy of protracted discussion, but what I mean
is that the natural, simplest implementation of function return would
not (as well as historically did not) invent well-defined values for
programs that do not at all specify the values.  In the case of default
initialization of statics, while it may appear that the programmer has
left the contents unspecified, he really hasn't, because K&R guaranteed
that they would contain 0.  There was never any guarantee that return
from an int-valued function would create some well-defined value (say,
0), but K&R did make it clear that so long as one didn't intend to use
a value there was no need to return one.  (This may have been different
if void-valued functions had existed from the beginning.)  As the only
acknowledged public specification of the C language, K&R had to be
taken as the main guide for settling questions about the existing rules.

Given that anonymous return in general produces an unspecified value,
anonymous return from main() naturally would do the same.  To make it
different from other functions would require a special-case wart, and
the one the standard already requires (accepting "int main(void)") was
already rather controversial.  ("int main(void)" would probably not
have been blessed were it not for the fact that K&R indicated clearly
that programmers could expect it to work, so there was a huge amount of
existing, arguably correct, code that relied on that behavior.)

While you can argue that you would like to add some more default rules
such as automatic 0 values for anonymous returns, that qualifies as new
invention and thus joins literally hundreds of similar suggestions in
the "not appropriate for standardization" category.

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (06/30/91)

In article <16587@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
> Given that anonymous return in general produces an unspecified value,
> anonymous return from main() naturally would do the same.

Hold on. You're saying something about the real world here, and the real
world doesn't distinguish between ``implementation-defined'' and
``undefined'' until a standard comes along and forces the issue. ANSI
could easily have left these decisions up to the implementation, and you
haven't given any excuse for the undefined behavior that wouldn't apply
equally well to implementation-defined behavior.

Or are you claiming that ANSI never forced implementations to define
behaviors where the behavior in general produced unspecified effects? I
think not. If that were so, ``implementation-defined'' wouldn't even be
in the standard. Everything would be ``undefined.''

> While you can argue that you would like to add some more default rules
> such as automatic 0 values for anonymous returns,

Yikes, why would I argue for something like that? I was just giving an
example of what an implementation could do to define the value. Nobody
in his right mind would standardize such a rule when it breaks so many
existing implementations for no good reason.

---Dan

gwyn@smoke.brl.mil (Doug Gwyn) (06/30/91)

In article <16020.Jun3004.44.3491@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Hold on. You're saying something about the real world here, and the real
>world doesn't distinguish between ``implementation-defined'' and
>``undefined'' until a standard comes along and forces the issue.

Sure it does.  If it core dumps, it's undefined, and if it's documented
in the long shelf of vendor literature, it's implementation-defined.