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

Why int main()?

2 views
Skip to first unread message

Huw Ford

unread,
Apr 11, 2003, 5:52:12 AM4/11/03
to
Why was main defined as returning int?
A lot of my work has been with embedded devices where the program never
returns from main.
For example main would look like this;

int main(int argc,char* argv[])
{
while(true)
{
DoThings();
};
return 0;
}

The return value should never be reached and even if main did return there
would be nothing that could be done with the return value.
A lot of compilers will accept "void main()" so why must main return an int?

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

Ben Hutchings

unread,
Apr 11, 2003, 2:49:04 PM4/11/03
to
In article <Qbvla.955$5Z2....@newsfep1-win.server.ntli.net>,

"Huw Ford" wrote:
> Why was main defined as returning int?
> A lot of my work has been with embedded devices where the program never
> returns from main.

Then you're probably working with freestanding implementations, where the
entry point is implementation-defined, so it might not be called main and
might not be expected to return int. (Section 3.6.1 paragraph 1.)

<snip>


> A lot of compilers will accept "void main()" so why must main return an
> int?

In most environments, a terminating process returns some kind of status
value indicating at least success or failure. Logically main() should
return a value that becomes this status value. At least some C compilers
treat main() just like any other function, and their startup code expects
it to return an int. This could have been changed in C++, since C++
compilers do have to treat main() specially in some respects, but why
change it when a return type of int is logically correct?

Randy Maddox

unread,
Apr 11, 2003, 2:49:29 PM4/11/03
to
H...@Tesco.net ("Huw Ford") wrote in message news:<Qbvla.955$5Z2....@newsfep1-win.server.ntli.net>...

> Why was main defined as returning int?
> A lot of my work has been with embedded devices where the program never
> returns from main.
> For example main would look like this;
>
> int main(int argc,char* argv[])
> {
> while(true)
> {
> DoThings();
> };
> return 0;
> }
>
> The return value should never be reached and even if main did return there
> would be nothing that could be done with the return value.
> A lot of compilers will accept "void main()" so why must main return an int?
>

Because that's what the C++ Standard specifies in subclause 3.6.1?

Seriously, although your situation is different, many applications do
need to return a value of some type to the OS to let the user know
whether the program was succesful or had a problem. Since this is
such a common need a standard way of supplying such a value had to be
specified. Obviously if every program had its own way of reporting
its termination status there would be no way for that to work
portably. So the writers of the C++ Standard chose the same behavior
as was already long specified for C programs as the way to provide
this commonly needed functionality.

Compilers that accept void main() are providing a non-standard
extension. It may work fine for you in a particular case, but it is
not standard behavior and you cannot expect it to be portable.

Randy.

Ken Hagan

unread,
Apr 11, 2003, 2:49:39 PM4/11/03
to
"Huw Ford" wrote:
> Why was main defined as returning int?

I'd guess ... because the remit of the original *C* committee was to
standardise existing practice and such practice was overwhelmingly
that of UNIX (and its offshoots such as MS-DOS). The return value is
useful there.

It's probably not a good way to design a language, but it does have
the merit that existing practice is known to work, at least for those
practising it.

Ron Natalie

unread,
Apr 11, 2003, 2:50:03 PM4/11/03
to

""Huw Ford"" <H...@Tesco.net> wrote in message news:Qbvla.955$5Z2....@newsfep1-win.server.ntli.net...

> Why was main defined as returning int?

Tradition. There was no void in early implementation, so main returned int
by default. Later, C was pretty well entrenched in the UNIX concept of the
return value of main being passed back as a program status.

> A lot of my work has been with embedded devices where the program never
> returns from main.

Embedded devices are not required to have any constraints on main (or even to
have a main).

> A lot of compilers will accept "void main()" so why must main return an int?

You are lucky that they do. The main reason you get away with it is that the
void and int returns coexist benignly. But the standard specifically says
main returns int, compilers that do so (without a diagnostic) are technically
incorrect. Change main to return a class or something large and I suspect
you'd run into a lot more places where it didn't work than where it did.

For a more pragmatic reason, think of it this way. In C++, both the caller
of the function and the called function definition must have the same type.
Now for most functions, you control both sides, you are free to redefine
the type of your functions. However, you don't call main. It is called by
the startup code for you. You can't just unilaterally change it to what you
want.

Francis Glassborow

unread,
Apr 11, 2003, 2:50:42 PM4/11/03
to
In article <Qbvla.955$5Z2....@newsfep1-win.server.ntli.net>, Huw Ford
<H...@Tesco.net> writes

>A lot of compilers will accept "void main()" so why must main return an int?

Because Standards are about portability. It is easy for a system to
ignore a return value when it does not need one, it is much harder to
create one where it is needed and none has been provided.

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow ACCU

Chris Putnam

unread,
Apr 11, 2003, 3:49:59 PM4/11/03
to
I believe this originated in order for UNIX programs to return an error code
to the process or shell that launched the program. Among other things, this
allows a shell scripting language (such as CSH or Windows batch files) to
execute code conditionally depending on the result of a previous command.

In my experience, compilers that accept the void main() signature do so by
providing a wrapper function to match whatever signature the OS requires.
For instance, if the OS needs an int main( int argc, char *argv) signature,
the compiler/linker might provide the following wrapper for the OS to call:

int wrapper_main( int argc, char *argv)
{
main();
return 0;
}

In this case, the compiler arranges for the OS to call wrapper_main()
instead.

Chris

""Huw Ford"" <H...@Tesco.net> wrote in message
news:Qbvla.955$5Z2....@newsfep1-win.server.ntli.net...

Ron Natalie

unread,
Apr 11, 2003, 4:03:48 PM4/11/03
to

""Chris Putnam"" <nosp...@attbi.com> wrote in message news:10500875...@hqnntp01.autodesk.com...

> In my experience, compilers that accept the void main() signature do so by
> providing a wrapper function to match whatever signature the OS requires.

Not in my experience. In my experience it is because the way the subroutine
linkage works, you can get away with mixing up void and int returns. Typically
an int return is just a value in one of the general purpose registers so the only
difference is the setting or omitting setting a value in the register.

It's just sheer luck that it works. Try this:

struct {
char x[100];
} main() {
}

and see what happens.

James Dennett

unread,
Apr 11, 2003, 6:54:02 PM4/11/03
to
Francis Glassborow wrote:
> In article <Qbvla.955$5Z2....@newsfep1-win.server.ntli.net>, Huw Ford
> <H...@Tesco.net> writes
>
>> A lot of compilers will accept "void main()" so why must main return
>> an int?
>
>
> Because Standards are about portability. It is easy for a system to
> ignore a return value when it does not need one, it is much harder to
> create one where it is needed and none has been provided.

And yet there's a wart in C++ because main is the _only_
function returning int where we do not have to providfe a
return value when the function exits, as a default value
is indeed provided.

Standardising void main() as being the same as int main()
but not allowing an expression after return, and acting
as if it was int main() returning 0, would be quite
possible technically. It would gain nothing except to
silence the endless discussion of why void main is not
legal.

It's trivial to turn a program with void main into a legal
one: s/void main/int main/. A saving of one character,
and the code becomes standard C++ (in that aspect at least).

-- James.

Jack Klein

unread,
Apr 12, 2003, 1:10:19 AM4/12/03
to
On Fri, 11 Apr 2003 22:54:02 +0000 (UTC), jden...@acm.org (James
Dennett) wrote in comp.std.c++:

> Francis Glassborow wrote:
> > In article <Qbvla.955$5Z2....@newsfep1-win.server.ntli.net>, Huw Ford
> > <H...@Tesco.net> writes
> >
> >> A lot of compilers will accept "void main()" so why must main return
> >> an int?
> >
> >
> > Because Standards are about portability. It is easy for a system to
> > ignore a return value when it does not need one, it is much harder to
> > create one where it is needed and none has been provided.
>
> And yet there's a wart in C++ because main is the _only_
> function returning int where we do not have to providfe a
> return value when the function exits, as a default value
> is indeed provided.

In the opinion of many, myself included, that was a mistake. It
appears to me to be a sop to those who whined about having to type a
"return 0;". At that it was better than standardizing "void main()",
and of course there might be other reasons I am not aware of.

Sadly, the C standard has done this as well, with even less
justification, as main() is not unique in C the way it is in C++.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq

Alexander Terekhov

unread,
Apr 12, 2003, 11:22:35 PM4/12/03
to

Francis Glassborow wrote:
>
> In article <Qbvla.955$5Z2....@newsfep1-win.server.ntli.net>, Huw Ford
> <H...@Tesco.net> writes
> >A lot of compilers will accept "void main()" so why must main return an int?
>
> Because Standards are about portability. ....

In the next round, I'd probably try to make {thread::}main's return
type "application-chosen" -- other thread(s) (if any) could then join
and obtain whatever-return-value (if it's not void)... and adopt a
rather simple POSIX behavior of "passive exit" on last thread
termination. Oder? ;-)

regards,
alexander.

Allan W

unread,
Apr 15, 2003, 8:01:10 PM4/15/03
to
tere...@web.de (Alexander Terekhov) wrote

> In the next round, I'd probably try to make {thread::}main's return
> type "application-chosen" -- other thread(s) (if any) could then join
> and obtain whatever-return-value (if it's not void)... and adopt a
> rather simple POSIX behavior of "passive exit" on last thread
> termination. Oder? ;-)

That's assuming a lot.

Let's assume that every conforming C++ compiler will have to support
threads (a huge assumption!). Let's further assume that when one thread
terminates, some other thread (at least the one that spawned it in the
first place) is able to get the "return value," no matter how large
that might be.

You're still making two even bigger assumptions.
1) The process will live as long as *ANY* thread does. As opposed to,
"the process will live as long as the FIRST thread does." Seems to
me that some OS's won't support this directly; instead, the runtime
system will keep control of what the OS calls the main thread, and
it can spawn a thread to run a main program. The trouble with this
approach is that ALL programs are now multi-threaded.

2) Returning class data from the MAIN thread makes sense.

But what happens if the program has only one thread, and it returns
data of type customer? What will the OS do with a customer?

The OS needs to know if the program ran successfully or not; if not,
it might need some indication of generally what went wrong. This
sounds a lot like the integer scheme currently in use on all Unix
systems, and carefully cloned on almost all other systems (including
the MSDOS-subsystem of all Microsoft Windows platforms).

James Kanze

unread,
Apr 15, 2003, 8:01:37 PM4/15/03
to
tere...@web.de (Alexander Terekhov) wrote in message
news:<3E9821CE...@web.de>...
> Francis Glassborow wrote:

> > In article <Qbvla.955$5Z2....@newsfep1-win.server.ntli.net>, Huw Ford
> > <H...@Tesco.net> writes
> > >A lot of compilers will accept "void main()" so why must main
> > >return an int?

> > Because Standards are about portability. ....

> In the next round, I'd probably try to make {thread::}main's return
> type "application-chosen" -- other thread(s) (if any) could then join
> and obtain whatever-return-value (if it's not void)... and adopt a
> rather simple POSIX behavior of "passive exit" on last thread
> termination. Oder? ;-)

Interesting point of view. There are several interesting points, in
fact:

- Why int? That's what Unix and MS-DOS used, but it certainly isn't
universal. The logical solution would have been an implementation
defined type, main_t with only the return of the macros EXIT_SUCCESS
and EXIT_FAILURE guaranteed by the standard. That would have broken
a lot of existing programs, however.

- Why not allow void? Either define falling off the end of a void
main as equivalent to return EXIT_SUCCESS from a non-void main, or
say that any return value is undefined (which is what actually
happens in most implementations today). Or say that returning from
a void main is illegal (undefined behavior) -- generally, when
people write void main, it is because they don't return, either
because the program consists of an endless loop, or because they
always call exit.

- And the business of threads introduces additional issues. Posix
threads return a void*, for example, and not an int. Logically, I
would expect a process to act sort of like a thread in the overall
system, with a similar sort of return value. On the other hand,
existing practice...

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

James Kanze

unread,
Apr 15, 2003, 8:01:47 PM4/15/03
to
r...@sensor.com ("Ron Natalie") wrote in message
news:<i1Fla.21842$eo4....@fe10.atl2.webusenet.com>...

> ""Chris Putnam"" <nosp...@attbi.com> wrote in message
> news:10500875...@hqnntp01.autodesk.com...

> > In my experience, compilers that accept the void main() signature do
> > so by providing a wrapper function to match whatever signature the
> > OS requires.

> Not in my experience. In my experience it is because the way the
> subroutine linkage works, you can get away with mixing up void and int
> returns. Typically an int return is just a value in one of the
> general purpose registers so the only difference is the setting or
> omitting setting a value in the register.

> It's just sheer luck that it works.

That and the fact that compiler writers don't like unnecessarily
breaking user code, even if the code is wrong.

> Try this:

> struct {
> char x[100];
> } main() {
> }

> and see what happens.

Works on my machine (Sun Sparc, Solaris, gcc 3.2.2 and Sun CC):-).
After I'd modified it so that the type wasn't defined in the return
value, of course.

With gcc, I had to compile it as C. G++ won't accept a return type
other than int. (Sun CC warns about an anachronism. I don't know when
they thought this was legal.)

If I add a return statement with a value, it core dumps. And I suspect
that on Intel processors, trying to use argc and argv in main will get
you into trouble as well. But your example works. (I know what you
were trying to say, and agree 100%. It's just that just saying try this
is a dangerous way to point it out, unless you're sure that it will fail
on all implementations.)

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

Ron Natalie

unread,
Apr 15, 2003, 8:02:43 PM4/15/03
to

"Jack Klein" <jack...@spamcop.net> wrote in message news:9k6f9vkh1959gdaln...@4ax.com...

> In the opinion of many, myself included, that was a mistake. It
> appears to me to be a sop to those who whined about having to type a
> "return 0;". At that it was better than standardizing "void main()",
> and of course there might be other reasons I am not aware of.
>

Actually, it's even stupider than that. It was a SOP for those who insist
that Dennis's original "Hello World" program still be valid C (the stupidity
is just one carried over from C). Of course it's particularly stupid because
even in C, there is no implicit int anymore, so the program doesn't compile
anyway.

Ron Natalie

unread,
Apr 15, 2003, 8:02:48 PM4/15/03
to

"Alexander Terekhov" <tere...@web.de> wrote in message news:3E9821CE...@web.de...
\

>
> In the next round, I'd probably try to make {thread::}main's return
> type "application-chosen" -- other thread(s) (if any) could then join
> and obtain whatever-return-value (if it's not void)... and adopt a
> rather simple POSIX behavior of "passive exit" on last thread
> termination. Oder? ;-)
>
How is the application supposed to chose. Ask yourself, who
calls main? It's not normally anything that's under the application
control.

Alexander Terekhov

unread,
Apr 16, 2003, 10:10:58 AM4/16/03
to

< c.p.t. added >

Ron Natalie wrote:
>
> "Alexander Terekhov" <tere...@web.de> wrote in message news:3E9821CE...@web.de...
> \
> >
> > In the next round, I'd probably try to make {thread::}main's return
> > type "application-chosen" -- other thread(s) (if any) could then join
> > and obtain whatever-return-value (if it's not void)... and adopt a
> > rather simple POSIX behavior of "passive exit" on last thread
> > termination. Oder? ;-)
> >
> How is the application supposed to chose. Ask yourself, who
> calls main? It's not normally anything that's under the application
> control.

The implementation calls main(). As for "application control"...

<dreams on>

#include <thread>
#include <iostream>

typedef std::joinable_thread_ptr<const char *> main_thread_ptr;

void f(main_thread_ptr mtp) {
main_thread_ptr::join_t result = mtp->cancel().join();
const char * msg = std::thread_canceled(result) ? "canceled" : *result;
std::cout << msg << std::endl;
}

const char * main() {
std::new_thread(&f, main_thread_ptr(std::thread_self()));
std::thread_testcancel();
return "hello world";
}

<dreams off>

-or- (status checking [and "old" C-style casts] aside for a moment...)

#include <cthread> // that's WG21-"controlled" <pthread.h>-"copy" ;-)
#include <iostream>
using namespace std;

extern "C" void * f(void * p) {
void * result;
pthread_t * pmain_tid = (pthread_t *)p;
pthread_cancel(*pmain_tid);
pthread_join(*pmain_tid, &result);
delete pmain_tid;
const char * msg = PTHREAD_CANCELED == result ?
"canceled" : (const char *)result;
cout << msg << endl;
return 0;
}

int main() {
pthread_t * pmain_tid = new pthread_t(pthread_self()), tid;
pthread_create(&tid, 0, &f, pmain_tid);
pthread_testcancel();
pthread_exit((void*)"hello world");
}

regards,
alexander.

--
http://tinyurl.com/9n1v
(Subject: Re: Next revision of boost::thread)

Alexander Terekhov

unread,
Apr 16, 2003, 10:11:45 AM4/16/03
to

Allan W wrote:
>
> tere...@web.de (Alexander Terekhov) wrote
> > In the next round, I'd probably try to make {thread::}main's return
> > type "application-chosen" -- other thread(s) (if any) could then join
> > and obtain whatever-return-value (if it's not void)... and adopt a
> > rather simple POSIX behavior of "passive exit" on last thread
> > termination. Oder? ;-)
>
> That's assuming a lot.

Let's see...

>
> Let's assume that every conforming C++ compiler will have to support
> threads (a huge assumption!).

Every conforming C++ implementation ALREADY supports "threads" -- one
thread per C++ program... or more than one... if it supports MULTIPLE
threads per C++ program.

> Let's further assume that when one thread
> terminates, some other thread (at least the one that spawned it in the
> first place) is able to get the "return value," no matter how large
> that might be.
>
> You're still making two even bigger assumptions.
> 1) The process will live as long as *ANY* thread does. As opposed to,
> "the process will live as long as the FIRST thread does."

That's not the way how things {currently ;-)} work out there.

> Seems to
> me that some OS's won't support this directly;

Do you know some OS that doesn't "support this directly"? I don't.

> instead, the runtime
> system will keep control of what the OS calls the main thread,

Main THREAD is nothing special. main() FUNCTION INVOCATION [which
is done by the implementation] is kinda-special... because instead
of doing

pthread_exit(main(/*...*/));

C/C++ implementations are required to do

exit(main(/*...*/));

That's it [the difference between C and C++ mains aside for a moment].

> and
> it can spawn a thread to run a main program. The trouble with this
> approach is that ALL programs are now multi-threaded.

Nope.

In [non-"braindamged" C++], pthread_exit() and cancel delivery shall
result in nothing "special"(*) other than raising some {standard}
exception. You don't really need multiple threads to have pthread_exit
[thread exit] and thread cancelation. You do need multiple threads
to join something, however.

>
> 2) Returning class data from the MAIN thread makes sense.

Threads don't return "class data". Thread routines COULD "return"
something (thread-exit "returns" including). Joinable [non-detached]
threads allow to retrieve those objects. In C++, "manual detach"
doesn't make much sense because it can be done "automatically" using
smart thread-object pointers. Just like you can ignore any function
return you'd be able to ignore any thread routine return. Again,
nothing special here as well.

>
> But what happens if the program has only one thread, and it returns
> data of type customer? What will the OS do with a customer?

The implementation will do nothing special other than destroying "a
customer" object.

>
> The OS needs to know if the program ran successfully

That's what "passive exit" on last thread termination is all about.

> or not; if not,
> it might need some indication of generally what went wrong. This
> sounds a lot like the integer scheme currently in use on all Unix

http://www.opengroup.org/sophocles/show_mail.tpl?source=L&listname=austin-review-l&id=1355
(Subject: Defect in XBD 3.297 Process Termination)

> systems, and carefully cloned on almost all other systems (including
> the MSDOS-subsystem of all Microsoft Windows platforms).

Thread cleanup aside, "passive exit" already works "just fine" on all
Microsoft Windows platforms. Well, why don't you simply try it? Hints:
ExitThread, _endthread, _endthreadex.

regards,
alexander.

(*) utterly silly "forced unwinding" aside for a moment.

Allan W

unread,
Apr 16, 2003, 3:27:43 PM4/16/03
to
ka...@gabi-soft.de (James Kanze) wrote
[re main() returning int]

> - Why int? That's what Unix and MS-DOS used, but it certainly isn't
> universal. The logical solution would have been an implementation
> defined type, main_t with only the return of the macros EXIT_SUCCESS
> and EXIT_FAILURE guaranteed by the standard. That would have broken
> a lot of existing programs, however.

Would it?

Suppose we insist that either main_t is a typedef for int, or else it
is convertible from int. Most programs would need only one trivial
change in order to be compatible; furthermore, on existing platforms,
the code would continue to function properly until this change was made.

> - Why not allow void? Either define falling off the end of a void
> main as equivalent to return EXIT_SUCCESS from a non-void main, or
> say that any return value is undefined (which is what actually
> happens in most implementations today). Or say that returning from
> a void main is illegal (undefined behavior) -- generally, when
> people write void main, it is because they don't return, either
> because the program consists of an endless loop, or because they
> always call exit.

That hasn't been my experience. Most of the uses of "void main" that
I've seen have been in textbooks! (Probably because I attack the
practice whenever I see it.) Saying that "void main" indicates that
the program never intends to exit is quite logical, but it doesn't
match existing practice very well.

I've been a strong proponent of ignoring void main, even when the
local platform supports it -- but my impression is that a LOT of
people routinely use it, without even realizing it's wrong. Which
makes me think that maybe we should support it after all. The C++
standard is supposed to document existing practice, yes?

Perhaps we should recognize any of these signatures:
int main(int, char**);
int main();
void main();

Allan W

unread,
Apr 16, 2003, 3:50:58 PM4/16/03
to
> > tere...@web.de (Alexander Terekhov) wrote
> > > In the next round, I'd probably try to make {thread::}main's return
> > > type "application-chosen" -- other thread(s) (if any) could then join
> > > and obtain whatever-return-value (if it's not void)... and adopt a
> > > rather simple POSIX behavior of "passive exit" on last thread
> > > termination. Oder? ;-)

> Allan W wrote:
> > That's assuming a lot.

tere...@web.de (Alexander Terekhov) wrote
> Let's see...

> > Let's assume that every conforming C++ compiler will have to support
> > threads (a huge assumption!).
>
> Every conforming C++ implementation ALREADY supports "threads" -- one
> thread per C++ program... or more than one... if it supports MULTIPLE
> threads per C++ program.

First, picking on nits of ambiguous language doesn't really clarify
the issue or advance the discussion in any meaningful way. Furthermore,
the word "threads" is plural...

Second, it's not even true. Look in the existing C++ standard for the
word "thread." You'll find it exactly once -- in 15.1/2 [except.throw],
in the phrase "thread of control," where it talks about exception
handlers. Clearly not a "thread" in the sense that you originally used it.

> > Let's further assume that when one thread
> > terminates, some other thread (at least the one that spawned it in the
> > first place) is able to get the "return value," no matter how large
> > that might be.
> >
> > You're still making two even bigger assumptions.
> > 1) The process will live as long as *ANY* thread does. As opposed to,
> > "the process will live as long as the FIRST thread does."
>
> That's not the way how things {currently ;-)} work out there.

Which is exactly my point. At least on some OS's (Microsoft Windows),
the initial thread is the "main" thread; when it exits, the program
terminates. But you said " 'passive exit' on last thread termination"
(quoted above) which is something else entirely.

> > 2) Returning class data from the MAIN thread makes sense.
>
> Threads don't return "class data". Thread routines COULD "return"
> something (thread-exit "returns" including). Joinable [non-detached]
> threads allow to retrieve those objects. In C++, "manual detach"
> doesn't make much sense because it can be done "automatically" using
> smart thread-object pointers. Just like you can ignore any function
> return you'd be able to ignore any thread routine return. Again,
> nothing special here as well.

The discussion was about return values from main(). Where are you
going with this?

> > But what happens if the program has only one thread, and it returns
> > data of type customer? What will the OS do with a customer?
>
> The implementation will do nothing special other than destroying "a
> customer" object.

Two problems with this.

First, you're suggesting that the return data is ignored. Why bother
returning data if it's going to be ignored? The current int value seems
more than sufficient -- precisely because it is NOT ignored on some OS's.

Second, think about the technical complications. You said that the
OS would destroy the customer object. Does that mean it runs the
destructor? The rest of the program has shut down, and all other
objects have been destroyed... what does it mean to destroy an object
when the rest of the run-time system has closed?

> > The OS needs to know if the program ran successfully
>
> That's what "passive exit" on last thread termination is all about.

But doesn't this break all existing programs?

> > or not; if not,
> > it might need some indication of generally what went wrong. This
> > sounds a lot like the integer scheme currently in use on all Unix
>
> http://www.opengroup.org/sophocles/show_mail.tpl?source=L&listname=austin-review-l&id=1355
> (Subject: Defect in XBD 3.297 Process Termination)
>
> > systems, and carefully cloned on almost all other systems (including
> > the MSDOS-subsystem of all Microsoft Windows platforms).
>
> Thread cleanup aside, "passive exit" already works "just fine" on all
> Microsoft Windows platforms. Well, why don't you simply try it? Hints:
> ExitThread, _endthread, _endthreadex.

But you can't use these on portable programs!

Ron Natalie

unread,
Apr 16, 2003, 3:51:32 PM4/16/03
to

"Allan W" <all...@my-dejanews.com> wrote in message news:7f2735a5.03041...@posting.google.com...

> Suppose we insist that either main_t is a typedef for int, or else it
> is convertible from int. Most programs would need only one trivial
> change in order to be compatible; furthermore, on existing platforms,
> the code would continue to function properly until this change was made.

Great more godawful changes that make main different than every other
function. This means more goofy stuff that has to get added to something
that knows it's compiling main and possibly additional linkage overhead
to support this.

> I've been a strong proponent of ignoring void main, even when the
> local platform supports it -- but my impression is that a LOT of
> people routinely use it, without even realizing it's wrong. Which
> makes me think that maybe we should support it after all. The C++
> standard is supposed to document existing practice, yes?

No. The practice was wrong before, it is wrong now. The C++ standard
only has a preference for things that were legal before, to avoid making them
illegal. void main has never been legal in C or C++. The fact that it
"happens to work OK" is not a compelling reason to codify the bad practice.

>
> Perhaps we should recognize any of these signatures:
> int main(int, char**);
> int main();
> void main();

The only reason that multiple signatures exist and are codified
in C++ is that early implementations worked fine when you passed unused
arguments. People got used to not being required to declare argc and argv
if they didn't use them, so the bad practice was standardized.

Stephen Howe

unread,
Apr 16, 2003, 5:26:52 PM4/16/03
to
> Actually, it's even stupider than that. It was a SOP for those who
insist
> that Dennis's original "Hello World" program still be valid C (the
stupidity
> is just one carried over from C). Of course it's particularly stupid
because
> even in C, there is no implicit int anymore, so the program doesn't
compile
> anyway.

Right.

I for one would sanction that main has to have a return statement in the
next standard. There is absolutely _NO_ good reason why main cannot behave
just like other functions if at all possible (I know it is special).
Dropping "off the bottom" of main is appalling and I am amazed that was
retained in the standard when implicit int was removed.

Stephen Howe

Al Grant

unread,
Apr 17, 2003, 1:44:39 PM4/17/03
to
SPAMstephe...@tnsofres.com ("Stephen Howe") wrote in message news:<3e9dc9fd$0$4860$ed9e...@reading.news.pipex.net>...

> I for one would sanction that main has to have a return statement in the
> next standard. There is absolutely _NO_ good reason why main cannot behave
> just like other functions if at all possible (I know it is special).
> Dropping "off the bottom" of main is appalling and I am amazed that was
> retained in the standard when implicit int was removed.

Right, there is no good reason why main cannot behave just like
other functions. But it is other functions that need fixing.
E.g. consider

void g(void);
int f(bool b) { if (b) return 1; g(); }

Should this be legal? Sure, if g() calls exit(), or longjmp(),
or throws an exception, or goes into an infinite loop.
The committee seem to have tentatively grasped the concept of
"non standard returns" in the context of main without accepting
its utility in general. Some compilers already provide a
"no return" annotation - evidently useful for the real world,
so why not add it to the language?

Ken Hagan

unread,
Apr 17, 2003, 1:45:03 PM4/17/03
to

===================================== MODERATOR'S COMMENT:
Warning: platform-specific topic drift.


===================================== END OF MODERATOR'S COMMENT


Allan W wrote:
>
> Which is exactly my point. At least on some OS's (Microsoft Windows),
> the initial thread is the "main" thread; when it exits, the program
> terminates. But you said " 'passive exit' on last thread termination"
> (quoted above) which is something else entirely.

This isn't quite true. Windows will keep a process alive until
all threads exit, unless one of the threads calls ExitProcess().
In practice, the main thread is spawned from a routine that
calls ExitProcess(), but there is nothing to stop either you
or your library vendor calling ExitThread() first.

Supporting passive termination on Windows would therefore be a
trivial modification to the vendor's startup code.

Alexander Terekhov

unread,
Apr 17, 2003, 1:45:16 PM4/17/03
to

Allan W wrote:
[...]

> > > You're still making two even bigger assumptions.
> > > 1) The process will live as long as *ANY* thread does. As opposed to,
> > > "the process will live as long as the FIRST thread does."
> >
> > That's not the way how things {currently ;-)} work out there.
>
> Which is exactly my point. At least on some OS's (Microsoft Windows),
> the initial thread is the "main" thread; when it exits, the program
> terminates. But you said " 'passive exit' on last thread termination"
> (quoted above) which is something else entirely.

I said: Thread cleanup aside, "passive exit" already works "just fine"
on all Microsoft Windows platforms. I've also asked you to simply try
to exit initial/main thread and see whether it will cause process
termination if the exiting thread isn't the last one.

>
> > > 2) Returning class data from the MAIN thread makes sense.
> >
> > Threads don't return "class data". Thread routines COULD "return"
> > something (thread-exit "returns" including). Joinable [non-detached]
> > threads allow to retrieve those objects. In C++, "manual detach"
> > doesn't make much sense because it can be done "automatically" using
> > smart thread-object pointers. Just like you can ignore any function
> > return you'd be able to ignore any thread routine return. Again,
> > nothing special here as well.
>
> The discussion was about return values from main(). Where are you
> going with this?

See the "examples" that I've posted to this thread. The second thread
can also be joined (you'd need another "joiner" thread, though).

[...]


> > > The OS needs to know if the program ran successfully
> >
> > That's what "passive exit" on last thread termination is all about.
>
> But doesn't this break all existing programs?

A *change* would break "some" programs, but not all.

http://groups.google.com/groups?selm=pEu_9.187%24_l3.134%40news.cpqcorp.net
-------------------------------------8<------------------------------------
>> > C99:
>> >
>> > "reaching the } that terminates the main function returns a
>> > value of 0."
>>
>> Interesting. I missed that. Well, it's consistent with the POSIX "passive
>> exit" when the last thread terminates.
>
> I wish they had defined it as "reaching the } that terminates
> the main function shall terminate the initial thread with the
> effect of executing pthread_exit(0)". ;-)

That could be a problem, since POSIX lacks Sun's "daemon thread" attribute.
That is, your change would rely on passive process exit rather than forcing
immediate exit, and some applications would simply cease to exit at all.

At least, for nonthreaded programs, it'd have the same effect as the C99
rule: the main thread is the only one, and its termination results in
passive process termination with the status 0.
-------------------------------------8<------------------------------------

Clearly, it would have to be another/additional "main() family" [preserving
the "old"/current one] in order to NOT break some existing progs.

regards,
alexander.

Ron Natalie

unread,
Apr 17, 2003, 3:16:25 PM4/17/03
to

"Al Grant" <alg...@myrealbox.com> wrote in message news:5765b025.03041...@posting.google.com...

> The committee seem to have tentatively grasped the concept of
> "non standard returns" in the context of main without accepting
> its utility in general.

You've lost me. It's already explicitly part of the language. The standard
says it's undefined behavior to fall off the bottom of a non-void function
OTHER THAN MAIN. The only thing that needs fixing is the "OTHER THAN
MAIN" exception.

James Kanze

unread,
Apr 23, 2003, 12:37:59 PM4/23/03
to
alg...@myrealbox.com (Al Grant) wrote in message
news:<5765b025.03041...@posting.google.com>...

> SPAMstephe...@tnsofres.com ("Stephen Howe") wrote in message
> news:<3e9dc9fd$0$4860$ed9e...@reading.news.pipex.net>...
> > I for one would sanction that main has to have a return statement in
> > the next standard. There is absolutely _NO_ good reason why main
> > cannot behave just like other functions if at all possible (I know
> > it is special). Dropping "off the bottom" of main is appalling and
> > I am amazed that was retained in the standard when implicit int was
> > removed.

> Right, there is no good reason why main cannot behave just like other
> functions. But it is other functions that need fixing. E.g. consider

> void g(void);
> int f(bool b) { if (b) return 1; g(); }

> Should this be legal?

It is legal, so the question should be: do we want to make it illegal.

> Sure, if g() calls exit(), or longjmp(), or throws an exception, or
> goes into an infinite loop.

For a more telling example, you should use a return which isn't int.
It's trivial to insert a return 0. But what do you do if the return
value is a user type which has no trivial constructors, and you have
nothing with which to call the constructors?

> The committee seem to have tentatively grasped the concept of "non
> standard returns" in the context of main without accepting its utility
> in general.

I'm not sure what the committee had in mind when they made the special
rules for int, but 1) the rules can't easily be extended to functions
returning user defined types, and 2) they don't change anything in the
case of functions where you don't fall off the end. I don't see any
need for the exception.

> Some compilers already provide a "no return" annotation - evidently
> useful for the real world, so why not add it to the language?

To solve what problem?

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

James Kanze

unread,
Apr 23, 2003, 12:38:10 PM4/23/03
to
r...@sensor.com ("Ron Natalie") wrote in message
news:<Lbina.6887$Y57....@fe05.atl2.webusenet.com>...

> "Allan W" <all...@my-dejanews.com> wrote in message
> news:7f2735a5.03041...@posting.google.com...
> > Suppose we insist that either main_t is a typedef for int, or else
> > it is convertible from int. Most programs would need only one
> > trivial change in order to be compatible; furthermore, on existing
> > platforms, the code would continue to function properly until this
> > change was made.

> Great more godawful changes that make main different than every other
> function. This means more goofy stuff that has to get added to
> something that knows it's compiling main and possibly additional
> linkage overhead to support this.

What needs to be added to the compiler? All I see here is a typedef of
main_t, in some header file.

> > I've been a strong proponent of ignoring void main, even when the
> > local platform supports it -- but my impression is that a LOT of
> > people routinely use it, without even realizing it's wrong. Which
> > makes me think that maybe we should support it after all. The C++
> > standard is supposed to document existing practice, yes?

> No. The practice was wrong before, it is wrong now. The C++ standard
> only has a preference for things that were legal before, to avoid
> making them illegal.

Before the C standard, anything a compiler implementor wanted to do was
legal:-). (On the other hand, this void main business seems to be a
recent phenomena. I can't recall seeing any void main in the days when
I was learning C.)

> void main has never been legal in C or C++.

I'd have to look that up in my K&R. C90 didn't explicitly ban it,
however.

> The fact that it "happens to work OK" is not a compelling reason to
> codify the bad practice.

What's bad about it (except the formal issues)? Most of my programs
never return.

> > Perhaps we should recognize any of these signatures:
> > int main(int, char**);
> > int main();
> > void main();

> The only reason that multiple signatures exist and are codified in
> C++ is that early implementations worked fine when you passed unused
> arguments. People got used to not being required to declare argc and
> argv if they didn't use them, so the bad practice was standardized.

I can buy that. (On the other hand, I can't remember ever writing a
program which didn't use argc and argv. For most of my work, the most
reasonable signature would be:

void main( int argc, char** argv ) ;
)

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

Ron Natalie

unread,
Apr 23, 2003, 1:03:51 PM4/23/03
to

"James Kanze" <ka...@gabi-soft.de> wrote in message news:d6651fb6.03042...@posting.google.com...

>
> What needs to be added to the compiler? All I see here is a typedef of
> main_t, in some header file.

I thought you were asking for the program to be able to change it.


>
> > void main has never been legal in C or C++.
>
> I'd have to look that up in my K&R. C90 didn't explicitly ban it,
> however.

You won't find the word void anywhere in K&R. Void didn't show up in
C until about 1978 or so. Your understanding of C90 is wrong. C90
is even more restrictive than C++. It requires the hosted environment
to do int main(void) and int main(int, char*[]), with no option for other
definition.

>
> > The fact that it "happens to work OK" is not a compelling reason to
> > codify the bad practice.
>
> What's bad about it (except the formal issues)? Most of my programs
> never return.

What's bad is what happens if you are on a machine where mismatching
void and int returns is not benign.

Thomas Mang

unread,
Apr 23, 2003, 10:17:48 PM4/23/03
to

James Kanze schrieb:

A point against "void main()":
It violates the overloading rules because we'd have then 2 functions differing
only in the return type.
OTOH, main is special anyways, why not make it special regarding this too,
since there is hardly an ambiguity to expect in practice........

regards,

Thomas

Ron Natalie

unread,
Apr 23, 2003, 10:24:47 PM4/23/03
to

"Thomas Mang" <a980...@unet.univie.ac.at> wrote in message news:3EA7067C...@unet.univie.ac.at...

> A point against "void main()":
> It violates the overloading rules because we'd have then 2 functions differing
> only in the return type.
> OTOH, main is special anyways, why not make it special regarding this too,
> since there is hardly an ambiguity to expect in practice........

Main is sort of reverse overloaded anyhow.

Francis Glassborow

unread,
Apr 24, 2003, 2:43:43 PM4/24/03
to
In article <3EA7067C...@unet.univie.ac.at>, Thomas Mang
<a980...@unet.univie.ac.at> writes

>A point against "void main()":
>It violates the overloading rules because we'd have then 2 functions differing
>only in the return type.
>OTOH, main is special anyways, why not make it special regarding this too,
>since there is hardly an ambiguity to expect in practice........

Actually, despite what the standard may say, I do not think that main is
a function in C++ (it is in C though a curiously overloaded one). You
cannot call it, you cannot take its address and the user cannot overload
it. Has the feel of an entry point with function like syntax.

We could get round many of people's quibbles with main if we wrote:

Every program running in a hosted environment has a single entry point
called main which has the following syntax:
...


--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

Risto Lankinen

unread,
Apr 24, 2003, 2:43:51 PM4/24/03
to

"Thomas Mang" <a980...@unet.univie.ac.at> wrote in message
news:3EA7067C...@unet.univie.ac.at...
>
> A point against "void main()":
> It violates the overloading rules because we'd have then 2 functions
differing
> only in the return type.

Not really because that, and int main(), would never
coexist in a single program since there would still be
just one main() function.

Cheers!

- Risto -

Allan W

unread,
Apr 24, 2003, 4:50:10 PM4/24/03
to
r...@sensor.com ("Ron Natalie") wrote
> "James Kanze" <ka...@gabi-soft.de> wrote

> > What needs to be added to the compiler? All I see here is a typedef of
> > main_t, in some header file.
>
> I thought you were asking for the program to be able to change it.

That's certainly not what I understood this to mean. (Since the
run-time system would be compiled before your definition, I can't
imagine this working properly anyway.)

All I meant was, this is how we allow implementation-defined return
types to work with standard programs. Just as the implementation can
use any reasonable integer type for size_t, it could do the same thing
for main_t.

Allan W

unread,
Apr 24, 2003, 4:55:24 PM4/24/03
to
a980...@unet.univie.ac.at (Thomas Mang)

> A point against "void main()":
> It violates the overloading rules because we'd have then 2
> functions differing only in the return type.

3.6.1/2 ... the main function... shall not be overloaded.

> OTOH, main is special anyways, why not make it special regarding this too,
> since there is hardly an ambiguity to expect in practice........

Can you imagine what would happen if a program had two global functions
named main()?
int main() { std::cout << "Version 1" << endl; }
int main(int, char**) { std::cout << "Version 2" << endl; }

If the implementation manages different signatures for main by using
the assembly-language concept called "weak references", then it will
end up calling whichever version of main that the start-up code
happens to check first. (Or maybe it calls BOTH of them, one after
the other!) If it uses some other technique, maybe it gets a linker
error. Otherwise I have no idea what to expect -- no, not a clue.

James Kanze

unread,
Apr 25, 2003, 2:03:45 PM4/25/03
to
r...@sensor.com ("Ron Natalie") wrote in message
news:<KJHpa.105$b9...@fe02.atl2.webusenet.com>...

> "Thomas Mang" <a980...@unet.univie.ac.at> wrote in message
> news:3EA7067C...@unet.univie.ac.at...

> > A point against "void main()":

> > It violates the overloading rules because we'd have then 2 functions
> > differing only in the return type.

The present situation is that we have one function differing in number
of parameters. Might as well go all out, and let it differ in
everything:-).

> > OTOH, main is special anyways, why not make it special regarding
> > this too, since there is hardly an ambiguity to expect in
> > practice........

> Main is sort of reverse overloaded anyhow.

Underloaded?

Practically speaking, in a language with more or less strict static
type checking, there should be one, and only one, legal definition for
main, say:

main_t main( int argc, char const* const* argv )

Anything else would be illegal.

For historical reasons, we don't have that luxury. An implementation
must support at least two versions, the return type of those two
versions must be int, and an integral value of 0 as the return value
must be interpreted as successful completion. The first condition is
awkward at best, and IMHO the last two are unnecessarily restrictive.
But it's too late for that now.

The only question is what restrictions should be imposed on
implementation defined additional versions. And my opinion is that
since they are implementation defined anyway, there is no reason for any
restrictions. If an implementation wants to add a:
double main( char*, float )
why not?

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

James Kanze

unread,
Apr 25, 2003, 2:03:48 PM4/25/03
to
r...@sensor.com ("Ron Natalie") wrote in message
news:<Rgzpa.11953$o21....@fe02.atl2.webusenet.com>...

> "James Kanze" <ka...@gabi-soft.de> wrote in message
> news:d6651fb6.03042...@posting.google.com...

> > What needs to be added to the compiler? All I see here is a typedef
> > of main_t, in some header file.

> I thought you were asking for the program to be able to change it.

You mean, dynamically change the return type of a function at run-time?
We could do that to, I suppose, but I don't think that the results
should be called C or C++. (Maybe lisp?)

> > > void main has never been legal in C or C++.

> > I'd have to look that up in my K&R. C90 didn't explicitly ban it,
> > however.

> You won't find the word void anywhere in K&R.

True. The standard way to implement a "void" function was to not
specify a return value, but formally speaking, that meant that the
function returned an int.

> Void didn't show up in C until about 1978 or so. Your understanding
> of C90 is wrong. C90 is even more restrictive than C++. It requires
> the hosted environment to do int main(void) and int main(int,
> char*[]), with no option for other definition.

The only copy of the standard I have handy is the one for C99; my copy
of the C90 standard is at home, and I am at the office. But I'm fairly
sure that this is one place where there wasn't a change, and the C99
standard very explicitly allows other forms. And I can explicitly
remember this being the case in C90 as well.

> > > The fact that it "happens to work OK" is not a compelling reason
> > > to codify the bad practice.

> > What's bad about it (except the formal issues)? Most of my programs
> > never return.

> What's bad is what happens if you are on a machine where mismatching
> void and int returns is not benign.

What's bad, then, is the same thing that is bad whenever you use an
implementation defined extension on a system which doesn't define it.
How is this any different than using:

int main( int argc, char** argv, char** env )

on a system which doesn't support it? It is quite clear that anything
BUT the two forms specified in the standard are in the realm of system
specific extensions.

BTW: do you (or anyone else, for that matter) actually know of a machine
where misdeclaring an int return type as void will cause problems if the
function doesn't return. I know that there are frequently differences
between int and a struct (often, if the return type is a struct, the
compiler will pass a hidden first parameter to the address of memory
where it should be returned), but I've never actually heard of a machine
that didn't return an int in a register.

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

Ron Natalie

unread,
Apr 25, 2003, 3:25:33 PM4/25/03
to

"James Kanze" <ka...@gabi-soft.de> wrote in message news:d6651fb6.03042...@posting.google.com...

>


> You mean, dynamically change the return type of a function at run-time?
> We could do that to, I suppose, but I don't think that the results
> should be called C or C++. (Maybe lisp?)

No, I thought you were asking that the programmer be able to define
an arbitrary main return type (at compile time).

> What's bad, then, is the same thing that is bad whenever you use an
> implementation defined extension on a system which doesn't define it.
> How is this any different than using:

Who's talking about implentation defined extension? I think the
thread got lost at some point. I thought we were talking about
required main signatures. Frankly, there really ought to only be
one (int main(int, char**)). The only reason C90 supported
otherwise (and now we're stuck with it), is that most (UNIX)
existing implmenetations just happened to do the right thing
if you under declared the actual number of arguments.

The more you require gunking up the main's function type, the more you make
it difficult for further implementations who don't use a subroutine linkage
compatible with assumptions made for PDP-11's.

> BTW: do you (or anyone else, for that matter) actually know of a machine
> where misdeclaring an int return type as void will cause problems if the
> function doesn't return. I know that there are frequently differences
> between int and a struct (often, if the return type is a struct, the
> compiler will pass a hidden first parameter to the address of memory
> where it should be returned), but I've never actually heard of a machine
> that didn't return an int in a register.

Nope, but do you want to preclude this? You were the one who wanted to
wide the type.

Allan W

unread,
Apr 27, 2003, 11:10:18 PM4/27/03
to
ka...@gabi-soft.de (James Kanze) wrote

> The only question is what restrictions should be imposed on
> implementation defined additional versions. And my opinion is that
> since they are implementation defined anyway, there is no reason for any
> restrictions. If an implementation wants to add a:
> double main( char*, float )
> why not?

It is already permitted for an implementation to accept a char* and
float. 3.6.1/2:
An implementation shall not predefine the main function. This
function shall not be overloaded. It shall have a return type
of int, but otherwise its type is implementation-defined. All
implementations shall allow both of the following definitions
of main:
int main() { /* ... */ }
and
int main(int argc, char*argv[]) { /* ... */ }

As for returning double instead of int -- consider 1.1/1:

This International Standard specifies requirements for
implementations of the C++ programming language. The first such
requirement is that they implement the language, and so this
International Standard also defines C++.

That, along with the definition of undefined behavior, allows the
compiler to do anything it wants with programs that are not compliant.
In other words -- a program which uses "double main(char*,float)" does
not comply with the C++ standard, and so it is not portable, but
there's no reason that individual implementations can't accept it.

James Kanze

unread,
Apr 29, 2003, 1:54:53 AM4/29/03
to
r...@sensor.com ("Ron Natalie") wrote in message
news:<uKeqa.21$7j...@fe02.atl2.webusenet.com>...

> "James Kanze" <ka...@gabi-soft.de> wrote in message
> news:d6651fb6.03042...@posting.google.com...

> > You mean, dynamically change the return type of a function at
> > run-time? We could do that to, I suppose, but I don't think that the
> > results should be called C or C++. (Maybe lisp?)

> No, I thought you were asking that the programmer be able to define an
> arbitrary main return type (at compile time).

Not that the programmer could definite it. What could the system
possibly do with a MyClass if I decide to return that.

The only thing I don't see is why given that we allow the implementation
to define additional signatures for main, we insist that these
additional, non-standard signatures have the return type int.

> > What's bad, then, is the same thing that is bad whenever you use an
> > implementation defined extension on a system which doesn't define
> > it. How is this any different than using:

> Who's talking about implentation defined extension?

I thought we were.

> I think the thread got lost at some point.

My impression as well.

> I thought we were talking about required main signatures. Frankly,
> there really ought to only be one (int main(int, char**)). The only
> reason C90 supported otherwise (and now we're stuck with it), is that
> most (UNIX) existing implmenetations just happened to do the right
> thing if you under declared the actual number of arguments.

Totally agreed.

I have no particular problem for allowing the implementation to define
additional signatures. I don't see a particular need for it, but again,
for historical reasons, we're probably stuck with at least allowing:

int main( int, char**, char** )

And if we allow additional, implementation defined signatures, I find
really only two defensible positions:

- an implementation may add additional arguments after the two in the
required signature, or

- an implementation can pretty much do whatever it wants.

We're somewhere between the two positions; something like:
int main( char*, double )
is a legal extension, but
void main( int, char** )
isn't. And I'll admit that I find THAT fairly arbitrary.

> The more you require gunking up the main's function type, the more you
> make it difficult for further implementations who don't use a
> subroutine linkage compatible with assumptions made for PDP-11's.

> > BTW: do you (or anyone else, for that matter) actually know of a
> > machine where misdeclaring an int return type as void will cause
> > problems if the function doesn't return. I know that there are
> > frequently differences between int and a struct (often, if the
> > return type is a struct, the compiler will pass a hidden first
> > parameter to the address of memory where it should be returned), but
> > I've never actually heard of a machine that didn't return an int in
> > a register.

> Nope, but do you want to preclude this? You were the one who wanted to
> wide the type.

Me. I didn't want anything. The only signature I ever use (regardless
of what the implementation supports) is "int main( int, char** )".
Logically, I would argue that 1) it would perhaps be better if the
implementation could define the return type (and the parameter type for
exit), and the only guaranteed legal values were EXIT_SUCCESS and
EXIT_FAILURE, and 2) IF we allow additional implementation defined
signatures (and we do), there is really no reason to restrict the return
type of THEM.

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

Ken Hagan

unread,
Apr 29, 2003, 1:18:45 PM4/29/03
to
James Kanze wrote:
>
> Me. I didn't want anything. The only signature I ever use
> (regardless of what the implementation supports) is "int main( int,
> char** )". Logically, I would argue that 1) it would perhaps be
> better if the implementation could define the return type (and the
> parameter type for exit), and the only guaranteed legal values were
> EXIT_SUCCESS and EXIT_FAILURE, and 2) IF we allow additional
> implementation defined signatures (and we do), there is really no
> reason to restrict the return type of THEM.

For (1), surely the logical signature is

bool main(/*your args here*/)

and if in future we go for "process lives until last thread exits"
then the logical return type for main() is void, with exit() being
the only sensible way to return a failure code to the OS. (For
thread "return values" it is a SMOP to leave arbitrary amounts of
information lying around where other threads can pick it up. I
see no merit in forcing anyone to pass that information through
the thread's startup routine.)

But, like you, I'm not campaigning for anything here. The current
rules force me to write an extra line of code. I can live with that.

Alexander Terekhov

unread,
Apr 29, 2003, 1:19:11 PM4/29/03
to

James Kanze wrote:
[...]

> > No, I thought you were asking that the programmer be able to define an
> > arbitrary main return type (at compile time).

That was me.

>
> Not that the programmer could definite it. What could the system
> possibly do with a MyClass if I decide to return that.

"The system" would simply terminate the initial/main thread.
Other thread(s) could presumably do something with a MyClass
object... after joining with the initial/main thread.

#include <thread>
#include <string>
#include <iostream>

typedef std::joinable_thread_ptr<std::string> main_thread_ptr;

void f(main_thread_ptr mtp) {
main_thread_ptr::join_t result = mtp->cancel().join();
const char * msg = std::thread_canceled(result) ?

"canceled" : result->c_str();


std::cout << msg << std::endl;
}

std::string main() {


std::new_thread(&f, main_thread_ptr(std::thread_self()));
std::thread_testcancel();

std::thread_exit(std::string("hello world"));
// Never reach here
return "";
}

regards,
alexander.

--
"If the } that terminates a function is reached, and the
value of the function call is used by the caller, the
behavior is undefined."
-- ISO/IEC 9899:1999

André Pönitz

unread,
May 7, 2003, 1:54:18 PM5/7/03
to
James Kanze <ka...@gabi-soft.de> wrote:
>> The fact that it "happens to work OK" is not a compelling reason to
>> codify the bad practice.
>
> What's bad about it (except the formal issues)? Most of my programs
> never return.

I think the only reason to insist on 'int main' is to have a means to
distinguish definitely bad books from possibly not so bad ones at a glance.

If an author writes 'void main()' it is not to expected that he pays much
attention on less obvious but more important details of the language.

If, OTOH, he writes 'int main()' he might be sufficiently pedantic and/or
lucky to get the rest of his book right ;-)

Andre'

--
Those who desire to give up Freedom in order to gain Security, will not have,
nor do they deserve, either one. (T. Jefferson or B. Franklin or both...)

0 new messages