Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

main function without a return statement in C99/C11

201 views
Skip to first unread message

Vincent Lefevre

unread,
May 4, 2012, 8:17:20 AM5/4/12
to
Concerning non-void functions without a return statement, the
C99 standard says (and it seems that C11 is identical):

5.1.2.2 Hosted environment

5.1.2.2.3 Program termination

1 If the return type of the main function is a type compatible
with int, 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;10) reaching
the } that terminates the main function returns a value of 0.
If the return type is not compatible with int, the termination
status returned to the host environment is unspecified.

6.9.1 Function definitions

12 If the } that terminates a function is reached, and the value
of the function call is used by the caller, the behavior is
undefined.

I can see 3 cases for hosted environments:

1. The initial call of the main function.
2. The other calls of the main function (when declared as returning
an int).
3. The other function calls.

Cases 1 and 3 are clearly specified. But case 2 is ambiguous. First,
6.9.1p12 doesn't exclude the main() function (it doesn't exclude it
either for case 1, but the caller being outside of the C environment
in this case, I don't see a contradiction with 5.1.2.2.3p1); that
would mean that the behavior is undefined if the value is used (see
an example below). 5.1.2.2.3p1 says that the main function returns
a value of 0, but this is not clear whether this applies to all the
calls to main, or only to the initial one. Based on 6.9.1p12 (which
doesn't exclude main), the fact that this specific rule for main is
under a section named "Program termination" and the fact that both
parts of the sentence are separated by a semi-colon (keeping the
context of the first part), I would say that it applies only for
the initial call (i.e. at program termination). But GCC 4.4 to 4.7
invoked with -std=c99 -Wreturn-type doesn't give a warning. What do
you think about this?

The example:

#include <stdio.h>

static int i = 0;

int main (void)
{
if (i++ == 0)
printf ("%d\n", main ());
}

The question is whether there is an undefined behavior (in which case
GCC should have given a warning) or this program should necessarily
output 0.

--
Vincent Lefèvre <vin...@vinc17.net> - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

Vincent Lefevre

unread,
May 4, 2012, 8:38:36 AM5/4/12
to
In article <20120504121658$12...@xvii.vinc17.org>,
Vincent Lefevre <vincen...@vinc17.net> wrote:

> Cases 1 and 3 are clearly specified. But case 2 is ambiguous. First,
> 6.9.1p12 doesn't exclude the main() function (it doesn't exclude it
> either for case 1, but the caller being outside of the C environment
> in this case, I don't see a contradiction with 5.1.2.2.3p1); that
> would mean that the behavior is undefined if the value is used (see
> an example below). 5.1.2.2.3p1 says that the main function returns
> a value of 0, but this is not clear whether this applies to all the
> calls to main, or only to the initial one. Based on 6.9.1p12 (which
> doesn't exclude main), the fact that this specific rule for main is
> under a section named "Program termination" and the fact that both
> parts of the sentence are separated by a semi-colon (keeping the
> context of the first part), I would say that it applies only for
> the initial call (i.e. at program termination). But GCC 4.4 to 4.7
> invoked with -std=c99 -Wreturn-type doesn't give a warning. What do
> you think about this?

I've found on Google Groups

http://groups.google.com/group/comp.std.c/msg/c2f56fecfb699952

where Clive D. W. Feather has the same reasoning as me (it's under
"Program termination", and 6.9.1p12 applies). So, I would say that's
a bug in GCC. Anyway, even for program termination, I think that an
implicit "return 0;" is a bad idea (just like most implicit things)
and a warning should be given. I'm going to report a bug...

lawrenc...@siemens.com

unread,
May 4, 2012, 11:43:42 AM5/4/12
to
Vincent Lefevre <vincen...@vinc17.net> wrote:
>
> 5.1.2.2.3 Program termination
>
> 1 If the return type of the main function is a type compatible
> with int, 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;10) reaching
> the } that terminates the main function returns a value of 0.
[...]
> 5.1.2.2.3p1 says that the main function returns
> a value of 0, but this is not clear whether this applies to all the
> calls to main, or only to the initial one.

It was intended to apply to all calls; the behavior of the function
itself shouldn't depend on whether it's the initial call or not.
--
Larry Jones

Well, it's all a question of perspective. -- Calvin

Vincent Lefevre

unread,
May 5, 2012, 5:27:43 AM5/5/12
to
In article <e2ad79-...@jones.homeip.net>,
lawrenc...@siemens.com wrote:

> Vincent Lefevre <vincen...@vinc17.net> wrote:
> >
> > 5.1.2.2.3 Program termination
> >
> > 1 If the return type of the main function is a type compatible
> > with int, 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;10) reaching
> > the } that terminates the main function returns a value of 0.
> [...]
> > 5.1.2.2.3p1 says that the main function returns
> > a value of 0, but this is not clear whether this applies to all the
> > calls to main, or only to the initial one.

> It was intended to apply to all calls;

Then I think that 6.9.1p12 should be modified to stop saying that
the behavior is undefined (in this case).

> the behavior of the function itself shouldn't depend on whether it's
> the initial call or not.

Note that in case the behavior is undefined, it doesn't make sense
to talk about it. But one could imagine an implementation doing
something equivalent to "exit(0);" at the end of main(), so that
the behavior wouldn't depend on whether it's the initial call or
not (i.e. in all cases, 0 is returned to the environment). The
standard should be made clear enough to rule out this possibility
if it is intended to behave like "return 0;".

lawrenc...@siemens.com

unread,
May 6, 2012, 2:07:06 PM5/6/12
to
Vincent Lefevre <vincen...@vinc17.net> wrote:
>
> Then I think that 6.9.1p12 should be modified to stop saying that
> the behavior is undefined (in this case).

Agreed. When trying to determine intent, a good rule of thumb is that
specific statements take precedence over generic ones, but you shouldn't
need to resort to that.

> Note that in case the behavior is undefined, it doesn't make sense
> to talk about it. But one could imagine an implementation doing
> something equivalent to "exit(0);" at the end of main(), so that
> the behavior wouldn't depend on whether it's the initial call or
> not (i.e. in all cases, 0 is returned to the environment).

That wouldn't be valid since main() is required to return like any other
function in the non-initial call case.
--
Larry Jones

Philistines. -- Calvin

Harald van Dijk

unread,
May 6, 2012, 2:28:26 PM5/6/12
to
On May 4, 5:43 pm, lawrence.jo...@siemens.com wrote:
> Vincent Lefevre <vincent-n...@vinc17.net> wrote:
> > 5.1.2.2.3p1 says that the main function returns
> > a value of 0, but this is not clear whether this applies to all the
> > calls to main, or only to the initial one.
>
> It was intended to apply to all calls; the behavior of the function
> itself shouldn't depend on whether it's the initial call or not.

I had expected that the reason for the current wording was for the
benefit of an implementation that returns all values via an extra
hidden pointer parameter, something that is already commonly done for
structures. On such an implementation, the return value, if no
explicit return statement is provided, is whatever the caller has
previously stored at that location. For the initial call, that would
be 0. For recursive calls, that would be garbage. In such an
implementation, it's not main that behaves differently when called
recursively, it's the call to main that's different. So such an
implementation must ensure that the result is set to 0 from within
main?
0 new messages