Q: recursive call to main, termination of program

S

Seong-Kook Shin

Hi, I'm reading Steve's "C Programming FAQs" in book version,
and have two question regarding to Q11.16

... Also, a `return' from `main' cannot be expected to work if
data local to main might be needed during cleanup. (Finally
the two forms are obviously not equivalent in a recursive call
to `main').

My questions are

1. Does ANSI standard say that these two forms of
termination of program might be different? I have C99 copy, and
it says..

5.1.2.2.3 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
`main' function returns a value of 0.

If these two forms are equivalent, from when are they equivalent?
ANSI? or C98? or C99?

2. Steve's mention to "recursive call" and C99's "initial call to the main".
I think that it is possible to call main() recursively. But I want
to make it
sure. Is it legal to call main() recursively? And if yes, can
anyone show me
practical (or concise at least) example of it?

3. Above C99 5.1.2.2.3, In "If the return type of the main is a type
compatible
..." Euh? Is it possible that main()'s return type is not compatible
with int?

I thought main should be one of these two forms:
int main(void) { ... }
int main(int argc, char *argv[]) { ... }

I'll thank you for your answers in advance.

Regards,
 
C

Chris Torek

1. Does ANSI standard say that these two forms of
termination of program might be different? I have C99 copy, and
it says..

5.1.2.2.3 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
`main' function returns a value of 0.

If these two forms are equivalent, from when are they equivalent?
ANSI? or C98? or C99?

There is something garbled in your quote here.

C89 and C99 differ a bit. If you are an implementor (the guy
writing the C compiler) and are implementing C89, you can implement
the initial call to main as, e.g.:

.global __libc_start
.entry __libc_start
__libc_start:

[ whatever special tricks are required to find argc and argv ]

[ here I assume they wind up in registers v0 and v1, which
are also the return-value registers for integer-valued
functions ]

/* now we just do: exit(main(argc, argv)) */
push v1 /* argv */
push v0 /* argc */
call main /* v0 = main(v0, v1) */
add #8,sp /* undo arguments */

push v0 /* main's return value is the desired exit status */
call exit /* exit(status) */
/* NOTREACHED */
halt /* "just in case" */

.end __libc_start

(you would write this in some kind of assembler language, typically).

Note that this passes main() exactly two arguments, and assumes
that passing two arguments to "int main(void)" is harmless. The
latter is usually true on most machines -- if not, you will need
to have your compiler tell you whether to call the two-argument
main() or the zero-argument main().

In C99, your job as compiler-and-library-writer is harder, because
C99 allows programs to "fall off the end" of main without returning
a value, and have main() act as if it ended with "return 0;" in
that case. That is:

int main(void)
{
}

and:

int main(void)
{
return 0;
}

are 100% identical programs in C99, but very different programs
in C89. You have to invent some mechanism to make this work in
C99.
2. Steve's mention to "recursive call" and C99's "initial call to the main".
I think that it is possible to call main() recursively. But I want
to make it
sure. Is it legal to call main() recursively? And if yes, can
anyone show me
practical (or concise at least) example of it?

Yes, and maybe:

#include <stdio.h>

int main(int argc, char **argv) {
if (argc > 1) {
main(argc - 1, argv + 1);
puts(argv[1]);
}
return 0;
}
3. Above C99 5.1.2.2.3, In "If the return type of the main is a type
compatible
..." Euh? Is it possible that main()'s return type is not compatible
with int?

I thought main should be one of these two forms:
int main(void) { ... }
int main(int argc, char *argv[]) { ... }

I'll thank you for your answers in advance.

It should indeed be, if you are writing a C program for any hosted
implementation.

Any implementation can, on the other hand, *allow* (but not require)
you to do something else to get some interesting and wanted (or
pointless, or unwanted, or even harmful) non-Standard behavior.
For instance, an implementor could decide that if you write:

double main(void) { }

and compile it, the resulting program will play Chess at grandmaster
level, but if the computer loses, make the computer burst into
flames.

Since Standard C cannot even draw graphics, much less let you play
chess with a display and mouse, this might be a big selling point.
Of course, this is a really bizarre way to do it; it would probably
be wiser, if you are the implementor, to provide non-Standard
<graphics.h>, <mouse.h>, and <chess.h> headers or some such. (The
auxiliary "sore loser" support might perhaps be in <badtemper.h>.)
 
K

Keith Thompson

Seong-Kook Shin said:
Hi, I'm reading Steve's "C Programming FAQs" in book version,
and have two question regarding to Q11.16

... Also, a `return' from `main' cannot be expected to work if
data local to main might be needed during cleanup. (Finally
the two forms are obviously not equivalent in a recursive call
to `main').

My questions are

1. Does ANSI standard say that these two forms of
termination of program might be different? I have C99 copy, and
it says..

5.1.2.2.3 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 `main' function returns a value of
0.

If these two forms are equivalent, from when are they equivalent?
ANSI? or C98? or C99?

It says "from the initial call", which excludes recursive calls.
2. Steve's mention to "recursive call" and C99's "initial call to the main".
I think that it is possible to call main() recursively. But I
want to make it sure. Is it legal to call main() recursively?
And if yes, can anyone show me practical (or concise at least)
example of it?

Yes, it's possible to call main recursively in C. <OT>C++ disallows
this.</OT>

There is no practical reason to call main recursively, unless you're
trying to write deliberately obfuscated code. But here's a silly
example:

#include <stdio.h>
int main(int argc, char **argv)
{
if (argc > 1) {
printf("%s ", argv[1]);
main(argc-1, argv+1);
}
else {
printf("\n");
}
return 0;
}
3. Above C99 5.1.2.2.3, In "If the return type of the main is a type
compatible
..." Euh? Is it possible that main()'s return type is not compatible
with int?

I thought main should be one of these two forms:
int main(void) { ... }
int main(int argc, char *argv[]) { ... }

C99 5.1.2.2.1 Program startup:

The function called at program startup is named main. The
implementation declares no prototype for this function. It shall
be defined with a return type of int and with no parameters:

int main(void) { /* ... */ }

or with two parameters (referred to here as argc and argv, though
any names may be used, as they are local to the function in which
they are declared):

int main(int argc, char *argv[]) { /* ... */ }

or equivalent; or in some other implementation-defined manner.
 
L

Lawrence Kirby

Hi, I'm reading Steve's "C Programming FAQs" in book version,
and have two question regarding to Q11.16

... Also, a `return' from `main' cannot be expected to work if
data local to main might be needed during cleanup. (Finally
the two forms are obviously not equivalent in a recursive call
to `main').

My questions are

1. Does ANSI standard say that these two forms of
termination of program might be different?

It follows from the fact that when you leave the block in which automatic
variables are defined, e.g. by returning from a function, those variables
cease to exist.
I have C99 copy, and
it says..

5.1.2.2.3 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
`main' function returns a value of 0.

This has been discussed in the past. There is a case for reading this as
calling exit() at the point (i.e. in the block) that the return statement
exists, but many people, including significantly compiler writers don't.
So just interpret the call to exit() as happening after main() has been
left. That's the likely intent.
If these two forms are equivalent, from when are they equivalent?
ANSI? or C98? or C99?

2. Steve's mention to "recursive call" and C99's "initial call to the
main".
I think that it is possible to call main() recursively. But I want
to make it
sure. Is it legal to call main() recursively? And if yes, can
anyone show me
practical (or concise at least) example of it?

It is supported, but there's no obvious use for it beyond IOCCC contests,
and puzzles such as writing shortest possible programs.
3. Above C99 5.1.2.2.3, In "If the return type of the main is a type
compatible
..." Euh? Is it possible that main()'s return type is not compatible
with int?

An implementation may support other return types. Compilers for Windows
systems seem to have a tendancy to support void as a return type, if you
could repeated use of such a form in their documentation examples as
"support".
I thought main should be one of these two forms:
int main(void) { ... }
int main(int argc, char *argv[]) { ... }


Those are the forms that the standard requires an implementation to
support, it doesn't forbid the implementation from supporting other forms.
What this means is that portable code should use one of these forms, or a
compatible one because other forms have undefined behaviour as far as the
standard is concerned.

Lawrence
 
K

Koollman

Keith Thompson said:
Seong-Kook Shin said:
2. Steve's mention to "recursive call" and C99's "initial call to the main".
I think that it is possible to call main() recursively. But I
want to make it sure. Is it legal to call main() recursively?
And if yes, can anyone show me practical (or concise at least)
example of it?

Yes, it's possible to call main recursively in C. <OT>C++ disallows
this.</OT>

There is no practical reason to call main recursively, unless you're
trying to write deliberately obfuscated code. But here's a silly
example:

#include <stdio.h>
int main(int argc, char **argv)
{
if (argc > 1) {
printf("%s ", argv[1]);
main(argc-1, argv+1);
}
else {
printf("\n");
}
return 0;
}

I have found one reason: I was making a shell, and was searching for a
'clean' way of conserving environment while using a kind of 'subshell'
(with the possibility of exporting variables from the subshell to the
main shell)

But I admit it was not the only way, and it was really weird to read
the main without comments...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top