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

int main() ???? wrong?

1 view
Skip to first unread message

Sid Lipkin

unread,
Aug 21, 1996, 3:00:00 AM8/21/96
to

I see alot of reference to int main () being incorrect syntax..
Ive gotten into the habit of doing it and would like to know what
errors could pop up in my code from not voiding main.

several books use int main() as examples and others use void main(void)


main returns an int i assume?

Thanks
Sid

Mike Rubenstein

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

sid...@lip.microserve.com (Sid Lipkin) wrote:

Get rid of the books that use void main(void). main returns an int.

int main() is correct, though many people prefer int main(void). This
is a matter of style -- they mean the same thing in a definition.

Michael M Rubenstein

Mike Ellis

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

Mike Rubenstein (mik...@ix.netcom.com) wrote:

: sid...@lip.microserve.com (Sid Lipkin) wrote:
: > I see alot of reference to int main () being incorrect syntax..
: > Ive gotten into the habit of doing it and would like to know what
: > errors could pop up in my code from not voiding main.

: int main() is correct, though many people prefer int main(void). This


: is a matter of style -- they mean the same thing in a definition.

Almost, but not quite.

"int main();" declares main as a function returning an int and taking an
unknown numbe of parameters - this is the old, K&R way of doing things
and may one day disappear from ANSI/ISO C.

However, "int main(void);" declares main as a function returning an
int and taking no parameters, and is to be preferred when using ISO
compliant compilers as it allows the compiler to type-check the
parameters (not a major issue for main, but very useful for all other
functions).

When used as a definition the same distinction applies, and the same
caveat about ISO one day removing support for the int main() construct
applies. Be safe - if you're not using a brain-dead compiler, always
use either "int main(void);" or "int main(int, char**);". Of course,
that should be "int main(int argc, char **argv)" for the definition
*only* - don't add the variable names to the declaration.

Cheers,

Mike.

--
Mike Ellis, Research and Development Engineer, BBC R & D
mike....@rd.bbc.co.uk DDI:(+44) 1737 836663 Fax:(+44) 1737 836667
BBC R&D, Kingswood Warren, Woodland Way, Tadworth, Surrey KT20 6NP, UK
Any opinions expressed are my own and may not reflect those of the BBC

Zach Heilig

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

sid...@lip.microserve.com (Sid Lipkin) writes:

> I see alot of reference to int main () being incorrect syntax..
> Ive gotten into the habit of doing it and would like to know what
> errors could pop up in my code from not voiding main.

there are exactly two correct declarations of main, and they are:

int main(void);

either or both types ('int' and 'void') may be left out in the above
example without any ill effect. If it is a definition, simply writing
'main()' will be equivalent.

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

the names of the arguments do not matter, however, the types do. Note
that in an argument list, 'char **foo' and 'char *foo[]' are 100%
equivalent. The return type may be omitted without changing the
meaning.

> several books use int main() as examples and others use void main(void)

Discard the books that use 'void main(void)'. Either the author
doesn't know enough about C to realize that main >MUST< return an int,
or (s)he is all too willing to throw the standard out the window when
convenient. In either case, it should be very difficult to trust the
validity of the rest of the book.

> main returns an int i assume?

That's exactly right.

--
Zach Heilig (za...@blizzard.gaffaneys.com) | ALL unsolicited commercial email
Support bacteria -- it's the | is unwelcome. I avoid dealing
only culture some people have! | with companies that email ads.

Lievre Ludovic

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

Zach Heilig wrote:

>
> > main returns an int i assume?
>
> That's exactly right.
>

What is the difference between

void main (void)
{
exit (-1);
}


int main (void)
{

return (-1);
}

I think that both functions returns -1;

--
Ludovic LIEVRE (lie...@racine.insa-tlse.fr)
http://mr.insa-tlse.fr/~lievre

-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS d- s+: a-- C++ ULS+ P L++ E W++ N++ o-- K- w---
O- M V- PS+ PE-- Y-- PGP- t+ 5+ X+ R++ tv b++ DI-- D+
G e+++ h r y++
------END GEEK CODE BLOCK------

Mike Ellis

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

Zach Heilig (za...@blizzard.gaffaneys.com) wrote:

: sid...@lip.microserve.com (Sid Lipkin) writes:
: > I see alot of reference to int main () being incorrect syntax..
: > Ive gotten into the habit of doing it and would like to know what
: > errors could pop up in my code from not voiding main.
:
: there are exactly two correct declarations of main, and they are:
:
: int main(void);
:
: either or both types ('int' and 'void') may be left out in the above
: example without any ill effect. If it is a definition, simply writing
: 'main()' will be equivalent.

Sorry, wrong on three counts. First, missing out the void turns valid
ISO/ANSI C into K&R C, and support for this syntax may be removed from
future versions of the ISO standard (ISO section 6.9.4 and 6.9.5).

Second, removing the int only works because the compiler will assume it
(ISO section 6.3.2.2) - FYI it also assumes an implicit "extern".
This behaviour will continue to be supported by the ISO standard, but
is prevents the compiler from doing return-value type-checking and
thus can lead to nasty, hard to find bugs in your code.

Third, missing out the void inhibits the compiler doing type
checking on the parameters, but parameters *may still be passed*.
Specifying the void means that *no* parameters may be passed. (ISO
section 6.5.4.3)

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


: the names of the arguments do not matter, however, the types do. Note

Sorry, wrong again. The names *do* matter as they are still subject
to the pre-processor. What would happen if the above line of code was
compiled with a macro "argc" defined to be something like 80...?
eg...

#define argc (80)
int main(int argc, char ** argv);

passed through the pre-processor becomes...

int main(int (80), char ** argv);

To quote gcc (not always an authority on these matters, but pretty
good...)

file.c:3: parse error before `80'
file.c:3: warning: function declaration isn't a prototype

Formal parameter names must *not* be given in the declaration
(prototype) for a function, although they *must* be given in the
definition. If you want to know what they are (after all, it can
make the code more readable) then use comments, thus

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

Mike Rubenstein

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

mi...@rd.bbc.co.uk (Mike Ellis) wrote:

> Mike Rubenstein (mik...@ix.netcom.com) wrote:
> : sid...@lip.microserve.com (Sid Lipkin) wrote:

> : > I see alot of reference to int main () being incorrect syntax..
> : > Ive gotten into the habit of doing it and would like to know what
> : > errors could pop up in my code from not voiding main.
>

> : int main() is correct, though many people prefer int main(void). This
> : is a matter of style -- they mean the same thing in a definition.
>
> Almost, but not quite.
>
> "int main();" declares main as a function returning an int and taking an
> unknown numbe of parameters - this is the old, K&R way of doing things
> and may one day disappear from ANSI/ISO C.
>
> However, "int main(void);" declares main as a function returning an
> int and taking no parameters, and is to be preferred when using ISO
> compliant compilers as it allows the compiler to type-check the
> parameters (not a major issue for main, but very useful for all other
> functions).
>
> When used as a definition the same distinction applies, and the same
> caveat about ISO one day removing support for the int main() construct
> applies. Be safe - if you're not using a brain-dead compiler, always
> use either "int main(void);" or "int main(int, char**);". Of course,
> that should be "int main(int argc, char **argv)" for the definition
> *only* - don't add the variable names to the declaration.

I'm sorry. It was really stupid of me to assume that just because
this is comp.lang.c we were talking about C, not some language that is
a figment of your imagination. Next time I'll try to remember to note
that my answer applies to the C language, not Mike Ellis's parody of
it.

It's not a question of whether the compiler is brain-dead. If it is
compiling C, there is no extra safety in defining int main(void) over
int main(). Both mean the same thing in a function definition.

I've no idea what ISO will or will not change in the language, but for
now (and, I expect, for many years to come) an empty parameter list in
a function definition means that the function has no parameters. It
is exactly equivalent to void.

From ISO 6.5.4.3:

An empty [parameter] list in a function declarator that is
part of a function definition specifies that the function has
no parameters.


Michael M Rubenstein

Jos A. Horsmeier

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

|What is the difference between
|
|void main (void)
|{
| exit (-1);
|}
|
|
|int main (void)
|{
|
| return (-1);
|}
|
|I think that both functions returns -1;

Phew, you were lucky then. Rumours say that the first version, after
an attempt to run it, turned the programmers' mother into a pile of
dandruff once, while at the same time a penguin appeared on top of
the terminal screen (other rumours stated that the penguin exploded
shortly afterwards).

A said example of undefined behavior in a hosted environment it is.
But tell those youngsters that an they won't believe you ...

kind regards,

Jos aka j...@and.nl (slightly silly)
--
Qgi nicws nt swaj ri rgw eufgr>


Tanmoy Bhattacharya

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

In article <321c564f...@nntp.ix.netcom.com>
mik...@ix.netcom.com (Mike Rubenstein) writes:
<snip>
MR: It's not a question of whether the compiler is brain-dead. If it is
MR: compiling C, there is no extra safety in defining int main(void) over
MR: int main(). Both mean the same thing in a function definition.

Not absolutely correct. It is true that the only prototyped
declaration compatible with int main() in a definition is
int main(void), however, there is a subtle difference. The following
code needs a diagnostic, but changing the declaration to `int main()'
would make this undefined behaviour not *needing* any diagnostic.

int main(void) {
int argc=3;
while (argc--) main(argc);
return 0;
}

Note that the following always needs a diagnostic, though:

int main() {
int(*fptr)(int) = main;
return 0;
}

Cheers
Tanmoy
--
tan...@qcd.lanl.gov(128.165.23.46) DECNET: BETA::"tan...@lanl.gov"(1.218=1242)
Tanmoy Bhattacharya O:T-8(MS B285)LANL,NM87545 H:#9,3000,Trinity Drive,NM87544
Others see <gopher://yaleinfo.yale.edu:7700/00/Internet-People/internet-mail>,
<http://alpha.acast.nova.edu/cgi-bin/inmgq.pl>or<ftp://csd4.csd.uwm.edu/pub/
internetwork-mail-guide>. -- <http://nqcd.lanl.gov/people/tanmoy/tanmoy.html>
fax: 1 (505) 665 3003 voice: 1 (505) 665 4733 [ Home: 1 (505) 662 5596 ]

R S Haigh

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

In article <4vhji6$p...@bbcnews.rd.bbc.co.uk>,
mi...@rd.bbc.co.uk (Mike Ellis) writes:

> Second, removing the int only works because the compiler will assume it
> (ISO section 6.3.2.2) - FYI it also assumes an implicit "extern".
> This behaviour will continue to be supported by the ISO standard, but
> is prevents the compiler from doing return-value type-checking and
> thus can lead to nasty, hard to find bugs in your code.

If the compiler assumes an implicit int by default, how or why is it
prevented from doing the same type-checking as if the int were explicit?

Is it even legal for it not to do so?

That is, if I write

extern func (void);
char *func(void) { ... }

or

extern func (void);
char *p;
p = func();

isn't a warning (at least) mandatory?


Sid Lipkin

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

On Wed, 21 Aug 1996 23:21:01 GMT, sid...@lip.microserve.com (Sid Lipkin) wrote:

>Im curious why do i see void main(void) so much?
what exactly is it saying? and why does it work ?

also if type int is implied and () is implied as an empty delaration (in ANSI)
why not main() (although ive never seen it)...

is return; implied return 0; ?

Sid

R S Haigh

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

In article <4vh5vj$k...@bbcnews.rd.bbc.co.uk>,
mi...@rd.bbc.co.uk (Mike Ellis) writes:

> "int main();" declares main as a function returning an int and taking an
> unknown numbe of parameters - this is the old, K&R way of doing things
> and may one day disappear from ANSI/ISO C.
>

> [...]


>
> When used as a definition the same distinction applies

I'm puzzled. If a function definition reads

int func () { ... }

how can the number of parameters be anything other than 0?

My compiler complains if I say

int func (void);
int func () { ... }

I can conceive of func being called with arguments, and func obtaining
access to those arguments by back-door extensions, but I still don't
see what changes if I write "int func (void)" instead. In either
case, I'm really (only?) saying that no local identifiers are being
associated with the contents of the argument frame.


Chris Engebretson

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

|> On Wed, 21 Aug 1996 23:21:01 GMT, sid...@lip.microserve.com (Sid Lipkin) wrote:

|> >Im curious why do i see void main(void) so much?
|> what exactly is it saying? and why does it work ?

This has been discussed to death.

|> is return; implied return 0; ?

No. A bare return returns nothing. This is fine if the function returns
void, but if it returns a non-void type, it introduces undefined behavior if
an external caller attempts to use the function's return value.

Regards,

--
/*-------------------------------------------------------------
Chris Engebretson // CSB - SED - Scientific Systems Development
United States Geological Survey - National Mapping Division
Mundt Federal Building, USGS EROS Data Center
Sioux Falls, SD 57198 http://edcwww.cr.usgs.gov/eros-home.html
email: enge...@edcserver1.cr.usgs.gov phone: 605-594-6829
-------------------------------------------------------------*/

The Amorphous Mass

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

sid...@lip.microserve.com wrote:
>
>Im curious why do i see void main(void) so much?

Some people have their own ideas about what the C language is, and
unfortunately they write books that people read. Apparently some people
think that there are times when you "don't want to return a value back
to the operating system." I can't think of any time when I wouldn't
want to. I've heard that it's easier for beginners to understand, but
I disagree -- what's easy about "a return value of void means the
function doesn't return a value?" And that's not even mentioning the
rather ominous nature of the word 'void'! :-)

>what exactly is it saying? and why does it work ?

It is saying, syntactically anyway, that main() takes no parameters and
does not return anything. I suspect that it works because a) C compilers
(especially on small machines) tend to assume that the programmer knows what
she's doing, and b) the authors don't want to be deluged with (bogus) bug
reports from furious adherents to the void main() religion. Some apparently
return 0; silently.

>also if type int is implied and () is implied as an empty delaration
>(in ANSI) why not main() (although ive never seen it)...

"main()" is very common, esp. in legacy code. K&R2 use it in almost all
the example code, and so do the Oracle and DEC manuals I have at my desk.

>is return; implied return 0; ?

No. return; means return from the current function; if the function is
not defined to return void, then it returns an undefined value to the
caller. As long as the caller doesn't try to use that value there's no
problem. So


#include <stdio.h>
foo() { puts("foo"); return; }
main() { foo(); return 0; }

is perfectly legal. return 0; means return the value 0 from the current
function. The Standard apparently allows the programmer to assume that
the environment that called main() will not try to use its return value, as

main() { foo(); }

is apparently also well-defined (although the return value is not).

/**James Robinson***********************
"An important goal of almost every graphics program is to draw pictures on
the screen." -- Neider, Davis & Woo, _OpenGL_Programming_Guide_, Chapter 10
*************james-r...@uiowa.edu**/

Dan Pop

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

>What is the difference between
>
>void main (void)
>{
> exit (-1);
>}

You didn't read the FAQ _before_ posting, right?

>int main (void)
>{
>
> return (-1);
>}

The difference is that the first one invokes undefined behaviour TWICE
(quite a remarkable feat for such a short program :-) while the second
invokes only implementation defined behaviour.

>I think that both functions returns -1;

The first one can do anything the compiler/computer wishes. The behaviour
of the second has to be documented by the implementor, but there is still
no requirement that the value -1 is returned to the execution environment.

Dan
--
Dan Pop
CERN, CN Division
Email: Dan...@cern.ch
Mail: CERN - PPE, Bat. 31 R-004, CH-1211 Geneve 23, Switzerland

Tanmoy Bhattacharya

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

In article <321C43...@mr.insa-tlse.fr>
Lievre Ludovic <lie...@mr.insa-tlse.fr> writes:

LL: Zach Heilig wrote:
LL:
LL: >
LL: > > main returns an int i assume?
LL: >
LL: > That's exactly right.
LL: >
LL:
LL: What is the difference between
LL:
LL: void main (void)
LL: {
LL: exit (-1);
LL: }
LL:
LL:
LL: int main (void)
LL: {
LL:
LL: return (-1);
LL: }
LL:
LL: I think that both functions returns -1;
LL:

The first function cannot `return -1' because a void function never
returns anything. The `exit' function cannot magically change a void
to an int!

The problem, as clearly explained in the FAQ, is that you have to
remember that main is a function. It is called just like any other
function, albeit not by your source code, rather by the C runtime
startup system. When the C startup was compiled, the declaration
presented to it had said that main returns an int: and the call to
main is based on that assumption.

Just as if you change the declaration of a function, you need to
recompile the caller as well as the called function, if you change the
declaration of main, you have to recompile the C startup code. On many
implementation, there are no visible ill-effects of calling a void
function when the caller thinks it is calling an int function because
the int result is passed in a register and not on stack. That accident
of implementation does not make it correct though: in fact if you
declare the return type of main to be a struct rather than int, on
many implementations it will crash!

Tanmoy Bhattacharya

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

In article <1996Aug22.1...@leeds.ac.uk>
ecl...@sun.leeds.ac.uk (R S Haigh) writes:

RSH: That is, if I write
RSH:
RSH: extern func (void);
RSH: char *func(void) { ... }
RSH:
RSH: or
RSH:
RSH: extern func (void);
RSH: char *p;
RSH: p = func();
RSH:
RSH: isn't a warning (at least) mandatory?
RSH:

Yes, the warning is required.

Howard Ham

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to
Ellis) wrote:

>: int main(int argc, char **argv);
>: the names of the arguments do not matter, however, the types do. Note
>
>Sorry, wrong again. The names *do* matter as they are still subject
>to the pre-processor.

The standard, in 5.1.2.2.1, disagrees with you:
"... 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)."

>Formal parameter names must *not* be given in the declaration
>(prototype) for a function, although they *must* be given in the
>definition.

I'm not sure why you think this. Writing parameter names in the
parameter list of a prototype is perfectly legal, and many people
prefer to use them. They go out of scope at the end of the prototype.

--Howard

Tanmoy Bhattacharya

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

In article <1996Aug22.1...@leeds.ac.uk>
ecl...@leeds.ac.uk (R S Haigh) writes:
<snip>
RSH: I'm puzzled. If a function definition reads
RSH:
RSH: int func () { ... }
RSH:
RSH: how can the number of parameters be anything other than 0?
RSH:

It is not. The only difference is that if you say `int func()' instead
of `int func(void)' when defining a function, (and no prototype is
actually visible), then you are requesting the compiler that it need
not complain if func is called with more than one parameter. Such a
call is still invalid, however: but who knows why you don't require a
warning.

RSH: My compiler complains if I say
RSH:
RSH: int func (void);
RSH: int func () { ... }
RSH:

What complaint? If a compiler refuses to compile that code (with
... replaced by something legal of course), it is not a C compiler. A
compiler is always free to give you warnings: nothing can be done
about that.

Ken Pizzini

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

In article <TANMOY.96A...@qcd.lanl.gov>,
Tanmoy Bhattacharya <tan...@qcd.lanl.gov> wrote:
>In article <4vhji6$p...@bbcnews.rd.bbc.co.uk>
>mi...@rd.bbc.co.uk (Mike Ellis) writes:
>ME: Formal parameter names must *not* be given in the declaration
>ME: (prototype) for a function, although they *must* be given in the
>ME: definition. If you want to know what they are (after all, it can
>ME: make the code more readable) then use comments, thus
>ME:
>
>We tend to avoid stylistic religious wars in this group. After all,
>what would happen if you had a
>
>#define main 80
>
>before
>
>ME: int main(int /* argc */, char ** /* argv */ );
>ME:
>
>:-)
>
>In fact, I belong to the opposite camp: I like giving the names of
>arguments in the headers: my declarations are identical to my
>definitions. My macros which are not supposed to mimic functions
>always start with capital letters and other names always with lowercase
>ones, so I have never found myself in any such bizarre problem. For
>that matter, why aren't you worried that in the definition stage you
>would still have #define argc (80)?

But naming parameters in the include files does cause a
namespace pollution issue. A a matter of documentation
I prefer the give-the-parameter-a-name-in-the-prototype
camp, but for widely used headers it is best to comment
out the names because the user shouldn't have to care
that "foo.h" happens to declare "int foo(int bar);"
and thus be forced to avoid defining bar before including
foo.h.

Yes, you still have to deal with the fact that the actual
variables and parameters in the implementaion are not
targets of spurious defines, but if the name spaces that
the headers define are adequately documented then it should
be easy enough to choose non-conflicting variable names.
And capitalization conventions help a lot too. Mike's
"must *not*" is a little strong, but the advice is still
good.

--Ken Pizzini

Tanmoy Bhattacharya

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

In article <321cc6d4....@news2.microserve.net>
sid...@lip.microserve.com (Sid Lipkin) writes:

SL:
SL: is return; implied return 0; ?
SL:

No.

If used in a context where return value is meaningful, it means return
garbage. Well, what happens after that is anybody's guess!

Dan Pop

unread,
Aug 22, 1996, 3:00:00 AM8/22/96
to

In <321cc6d4....@news2.microserve.net> sid...@lip.microserve.com (Sid Lipkin) writes:

>On Wed, 21 Aug 1996 23:21:01 GMT, sid...@lip.microserve.com (Sid Lipkin) wrote:
>
>>Im curious why do i see void main(void) so much?

>what exactly is it saying? and why does it work ?
>

>also if type int is implied and () is implied as an empty delaration (in ANSI)
>why not main() (although ive never seen it)...

Open K&R2 at page 6 and you'll see it.

>is return; implied return 0; ?

No.

Zach Heilig

unread,
Aug 23, 1996, 3:00:00 AM8/23/96
to Lievre Ludovic

Lievre Ludovic <lie...@mr.insa-tlse.fr> writes:

> Zach Heilig wrote:

> > > main returns an int i assume?

> > That's exactly right.

> What is the difference between

> void main (void) { exit (-1); }

A standard conforming program will only declare main() in one of
exactly two ways (or their *exact* equivalents), and both begin with
the three letters "int". Doing otherwise is begging for trouble.

> int main (void) { return (-1); }

> I think that both functions returns -1;

The catch is, only one is correct. One problem with the first, is
some linkers might fail to link. Consider a linker implemented like
this (I posted this idea back in September '94, but it needs to be
stated again :-):

Consider a compiler that, for debugging purposes, saves the type the
return value, and the types of each known parameter of every function.
The linker is then set up to fail to link if the types of the
parameters and return types are not bitwise-compatible. This would
prevent errors such as inconsistant prototypes in different
translation units. Of course 'void main()' would be seen as not
compatible with 'int main()' (we all know variables of type 'void' are
not assignment compatible with variables of type 'int' :-), but that
would be a minor "price" to pay to be sure that the function
prototypes of your whole project (of say 100,000+ lines of code) are
consistant.

Such a linker would be 100% standard conforming, since you invoke
undefined behaviour when you lie to the compiler about function
prototypes (if they are different between two separate translation
units, one of them is a lie).

If you are still wondering precisely why 'void main()' is lying to the
compiler about main(), and where the 'int main()' function prototype
is if you didn't write it, consider that the compiler has to link your
program with some sort of start up code (which doesn't have to be
written in 'C', but it in fact has to be written so it can link with
'C', so there is little difference in this case). This code expects
that 'main()' returns an "int", so any other return type is a lie.

BTW, -1 is NOT a standard conforming return value (from main()). The
three sanctioned return values are:

0 /* successful execution! */
EXIT_SUCCESS
EXIT_FAILURE

the latter two are turned on by #include'ing <stdlib.h>. Other values
may be used as an implementation specific extension.

Mark J. Bobak

unread,
Aug 23, 1996, 3:00:00 AM8/23/96
to

In article <321C43...@mr.insa-tlse.fr>,
Lievre Ludovic <lie...@mr.insa-tlse.fr> wrote:

:Zach Heilig wrote:
:
:>
:> > main returns an int i assume?
:>
:> That's exactly right.
:>
:
:What is the difference between
:
:void main (void)
:{
: exit (-1);
:}
:
:
:int main (void)

:{
:
: return (-1);
:}
:
:I think that both functions returns -1;

Hmm....well, that's not exactly true. How can the first version return -1 when
you have defined main() as void? But the standard specifies that main() returns
an int. This is just plain wrong. main() must be defined as int. Secondly,
the difference between using return (-1) and exit (-1) is that exit() checks
for functions registered with atexit(), all open streams are flushed and closed,
and files created by the tmpfile() function are removed. After that, control
goes back to the host environment, behavior is implementation defined.


-Mark
--
Mark J. Bobak, Application Developer
Advanced Vehicle & Computer Aided Engineering Systems Department
Process Leadership, Ford Motor Company
mbo...@ford.com

Zach Heilig

unread,
Aug 23, 1996, 3:00:00 AM8/23/96
to Mike Ellis

mi...@rd.bbc.co.uk (Mike Ellis) writes:

> Zach Heilig (za...@blizzard.gaffaneys.com) wrote:
> : int main(void);

> : either or both types ('int' and 'void') may be left out in the above
> : example without any ill effect. If it is a definition, simply writing
> : 'main()' will be equivalent.

> Sorry, wrong on three counts. First, missing out the void turns
> valid ISO/ANSI C into K&R C, and support for this syntax may be
> removed from future versions of the ISO standard (ISO section 6.9.4
> and 6.9.5).

Woah! slow down. 'int main(void) { ... }' and 'main() { ... }' are in
fact 100% equivalent. You cannot legally pass any parameters to
either function. Since the standard specifies that main() may accept
0 or 2 parameters of the appropriate type, you might be able to get
away with passing the appropriate parameters (in the case where you
declare main as taking none), but even that is not guaranteed. The
implementation may deal with the requirement that main() may be
declared both ways by having two separate startup libraries, and
linking the appropriate one depending on how main() is defined. If it
were viewed as a prototype, as in 'int main(void);' or 'int main();',
only the first is a prototype.

BTW, the only support that might be removed is the case where "double
foo();" may later be expanded to "double foo(double bar);".

> Second, removing the int only works because the compiler will assume
> it (ISO section 6.3.2.2) - FYI it also assumes an implicit "extern".
> This behaviour will continue to be supported by the ISO standard,
> but is prevents the compiler from doing return-value type-checking
> and thus can lead to nasty, hard to find bugs in your code.

I fail to see how the compiler can fail to do return value type
checking (as you put it) in the case of the omitted return type. The
compiler *KNOWS* if there is no return type specified that the return
type is 'int', so if it would have checked return types in the case of
a return type specified, it *STILL* can if there is none specified.

Omitting the return type (if it is 'int') changes *NOTHING*.

> Third, missing out the void inhibits the compiler doing type
> checking on the parameters, but parameters *may still be passed*.
> Specifying the void means that *no* parameters may be passed. (ISO
> section 6.5.4.3)

No, if a function definition doesn't specify any parameter types (e.g.
int main() { ... }), it is *ILLEGAL* to pass parameters to it, even if
the compiler will let you. In the case of a "prototype" (a prototype
without parameters specified is not really a prototype), you are
correct, but I was not speaking of a prototype, only a definition.

> : int main(int argc, char **argv);
> : the names of the arguments do not matter, however, the types do. Note

> Sorry, wrong again. The names *do* matter as they are still subject

> to the pre-processor. What would happen if the above line of code
> was compiled with a macro "argc" defined to be something like 80...?

And I say, SO WHAT!! If you do stupid things with the preprocessor,
you deserve every bit of grief you get.

My original point re-stated: the names of the parameters to main()
(typically argc and argv) DO NOT MATTER! (disclaimer for idiots: do
not do stupid things with the preprocessor).

> Formal parameter names must *not* be given in the declaration

> (prototype) for a function, although they *must* be given in the

> definition. If you want to know what they are (after all, it can

> make the code more readable) then use comments, thus

> int main(int /* argc */, char ** /* argv */ );

That is just plain wrong. The following line of code is 100% correct:

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

One method used before the standard was:

int main(/* int argc, char **argv */);, but you gain very little by
omitting the parameter names in the prototype by commenting them out.
Many people do omit parameter names (myself included), but it is in
no way manditory that you do omit them. My solution for the problem
of parameter documentation is a largish block comment before the
actual function describing the purpose and domain of each parameter,
among other useful data (written in such a way that it can be
mechanically extracted and included in a usage document if required).

Mike Rubenstein

unread,
Aug 23, 1996, 3:00:00 AM8/23/96
to

mik...@ix.netcom.com (Mike Rubenstein) wrote:

> mi...@rd.bbc.co.uk (Mike Ellis) wrote:
>
> > Mike Rubenstein (mik...@ix.netcom.com) wrote:
> > : sid...@lip.microserve.com (Sid Lipkin) wrote:
> > : > I see alot of reference to int main () being incorrect syntax..
> > : > Ive gotten into the habit of doing it and would like to know what
> > : > errors could pop up in my code from not voiding main.
> >
> > : int main() is correct, though many people prefer int main(void). This
> > : is a matter of style -- they mean the same thing in a definition.
> >
> > Almost, but not quite.
> >

> > "int main();" declares main as a function returning an int and taking an
> > unknown numbe of parameters - this is the old, K&R way of doing things
> > and may one day disappear from ANSI/ISO C.
> >

> > However, "int main(void);" declares main as a function returning an
> > int and taking no parameters, and is to be preferred when using ISO
> > compliant compilers as it allows the compiler to type-check the
> > parameters (not a major issue for main, but very useful for all other
> > functions).
> >
> > When used as a definition the same distinction applies, and the same
> > caveat about ISO one day removing support for the int main() construct
> > applies. Be safe - if you're not using a brain-dead compiler, always
> > use either "int main(void);" or "int main(int, char**);". Of course,
> > that should be "int main(int argc, char **argv)" for the definition
> > *only* - don't add the variable names to the declaration.
>
> I'm sorry. It was really stupid of me to assume that just because
> this is comp.lang.c we were talking about C, not some language that is
> a figment of your imagination. Next time I'll try to remember to note
> that my answer applies to the C language, not Mike Ellis's parody of
> it.
>

> It's not a question of whether the compiler is brain-dead. If it is

> compiling C, there is no extra safety in defining int main(void) over

> int main(). Both mean the same thing in a function definition.
>

> I've no idea what ISO will or will not change in the language, but for
> now (and, I expect, for many years to come) an empty parameter list in
> a function definition means that the function has no parameters. It
> is exactly equivalent to void.
>
> From ISO 6.5.4.3:
>
> An empty [parameter] list in a function declarator that is
> part of a function definition specifies that the function has
> no parameters.

Please forgive this response; you caught me at a bad moment. While it
is true that the standard says that an empty parameter list specifies
that a function has no parameters, as Tanmoy points out the standard
does not require a diagnostic if one later calls the function with an
argument, though it does if an attempt is made to convert the function
to a pointer to function that does have a prototype that includes a
parameter.


Michael M Rubenstein

Tanmoy Bhattacharya

unread,
Aug 23, 1996, 3:00:00 AM8/23/96
to

In article <4vkd4q$j...@eccdb1.pms.ford.com>
mbo...@pms991.uucp (Mark J. Bobak) writes:
<snip>
MJB: an int. This is just plain wrong. main() must be defined as int. Secondly,
MJB: the difference between using return (-1) and exit (-1) is that exit() checks
MJB: for functions registered with atexit(), all open streams are flushed and closed,
MJB: and files created by the tmpfile() function are removed. After that, control
MJB: goes back to the host environment, behavior is implementation defined.

To be absolutely precise, return from the initial call of main
activates the same sequence of events. The difference between the
return and exit is visible only if the local variables of main are
important to those activities.

Lievre Ludovic

unread,
Aug 23, 1996, 3:00:00 AM8/23/96
to Zach Heilig

Zach Heilig wrote:

> BTW, -1 is NOT a standard conforming return value (from main()). The
> three sanctioned return values are:
>
> 0 /* successful execution! */
> EXIT_SUCCESS
> EXIT_FAILURE
>
> the latter two are turned on by #include'ing <stdlib.h>. Other values
> may be used as an implementation specific extension.

I think there is a minor problem, because my stlib.h say that:

#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0

So in my stdlib.h there are only two sanctionned return values. Or maybe
my stlib is not standard (SunOs)

Ludo

--
/* lievre @mr.insa-tlse.fr */
int main(){char _1='_';int _0x01=0x01^0x01;
char *_="C{ic}cj(KO@RQG!h{z}6$%dz)okwb/ul|k#jy%wdncsvf";
while (_[_0x01]) putchar (_[_0x01]^_1&0xf^_0x01++&0xf);
putchar (0x14>>1);}

Chris Engebretson

unread,
Aug 23, 1996, 3:00:00 AM8/23/96
to

In article <321DFD...@mr.insa-tlse.fr>, Lievre Ludovic <lie...@mr.insa-tlse.fr> writes:

|> > BTW, -1 is NOT a standard conforming return value (from main()). The
|> > three sanctioned return values are:
|> >
|> > 0 /* successful execution! */
|> > EXIT_SUCCESS
|> > EXIT_FAILURE
|> >
|> > the latter two are turned on by #include'ing <stdlib.h>. Other values
|> > may be used as an implementation specific extension.
|>
|> I think there is a minor problem, because my stlib.h say that:
|>
|> #define EXIT_FAILURE 1
|> #define EXIT_SUCCESS 0
|>
|> So in my stdlib.h there are only two sanctionned return values. Or maybe
|> my stlib is not standard (SunOs)

Sure it's standard.

All that EXIT_SUCCESS and EXIT_FAILURE are are macros which expand to
integral expressions that may portably be used as the argument to the
exit() function. You're also guaranteed that a value of 0 will have the
same effect as using EXIT_SUCCESS in that it signals a successful
completion. (Note that there's no _requirement_ that EXIT_SUCCESS evaluate
to 0, only that their effects be equivalent.)

The rule of thumb that should be noted here:

1) To signify application failure, use "exit(EXIT_FAILURE);"

2) To signify application success, use "exit(EXIT_SUCCESS);" _or_
"exit(0);". (The fact that they are identical for your implementation
does not make it so universally.) Generally, the first form is to be
recommended since it is more descriptive.

Tanmoy Bhattacharya

unread,
Aug 23, 1996, 3:00:00 AM8/23/96
to

In article <4vihp8$5...@news1.halcyon.com>
k...@chinook.halcyon.com (Ken Pizzini) writes:
<snip>
KP: >In fact, I belong to the opposite camp: I like giving the names of
KP: >arguments in the headers: my declarations are identical to my
KP: >definitions. My macros which are not supposed to mimic functions
KP: >always start with capital letters and other names always with lowercase
KP: >ones, so I have never found myself in any such bizarre problem. For
KP: >that matter, why aren't you worried that in the definition stage you
KP: >would still have #define argc (80)?
KP:
KP: But naming parameters in the include files does cause a
KP: namespace pollution issue. A a matter of documentation
KP: I prefer the give-the-parameter-a-name-in-the-prototype
KP: camp, but for widely used headers it is best to comment
KP: out the names because the user shouldn't have to care
KP: that "foo.h" happens to declare "int foo(int bar);"
KP: and thus be forced to avoid defining bar before including
KP: foo.h.

Note that the only name space one is encroaching upon is of object
like macros: nothing stops you from saying

int bar;

or

#define bar(x)

before including "foo.h". The only thing you cannot say is things like

#define bar

KP:
KP: Yes, you still have to deal with the fact that the actual
KP: variables and parameters in the implementaion are not
KP: targets of spurious defines, but if the name spaces that
KP: the headers define are adequately documented then it should
KP: be easy enough to choose non-conflicting variable names.
KP: And capitalization conventions help a lot too. Mike's
KP: "must *not*" is a little strong, but the advice is still
KP: good.

As you can see once you insist that no object like macros look like
variable names, there is absolutely no problem. A simple
capitalization rule enforces that.

Advice like this is neither good nor bad. It depends on people's
preference. If they think that the strict capitalization is too much
of a price to pay, sure it is a bad thing. If they think that
capitalization of macro names that do not mimic a function is a good
thing, and they do it anyway, there is no problem.

Tanmoy Bhattacharya

unread,
Aug 23, 1996, 3:00:00 AM8/23/96
to

In article <321DFD...@mr.insa-tlse.fr>
Lievre Ludovic <lie...@mr.insa-tlse.fr> writes:

LL: Zach Heilig wrote:
LL:

LL: > BTW, -1 is NOT a standard conforming return value (from main()). The
LL: > three sanctioned return values are:
LL: >
LL: > 0 /* successful execution! */
LL: > EXIT_SUCCESS
LL: > EXIT_FAILURE
LL: >
LL: > the latter two are turned on by #include'ing <stdlib.h>. Other values
LL: > may be used as an implementation specific extension.
LL:
LL: I think there is a minor problem, because my stlib.h say that:
LL:
LL: #define EXIT_FAILURE 1
LL: #define EXIT_SUCCESS 0
LL:
LL: So in my stdlib.h there are only two sanctionned return values. Or maybe
LL: my stlib is not standard (SunOs)

No one said they have to be distinct! Three portable values exist:
even though one of them might expand to another.

Steve Summit

unread,
Aug 23, 1996, 3:00:00 AM8/23/96
to

In article <321b9857...@news2.microserve.net>,

sid...@lip.microserve.com writes:
> I see alot of reference to int main () being incorrect syntax..
> Ive gotten into the habit of doing it and would like to know what
> errors could pop up in my code from not voiding main.

I assume you mean, "what errors could pop up from not declaring
main correctly." Speaking generally, the same sorts of errors
could pop up as occur any time a global variable or function is
misdeclared.

Turning for a moment from main() and void to ints and doubles,
let's consider the (incorrect) code

#include <stdio.h>
extern int sqrt();
main()
{
printf("%d\n", sqrt(144.));
return 0;
}

This code is clearly trying to compute and print the square root
of 144, but it almost as clearly will not work. It declares
that the library function sqrt() returns an int, and it tries to
print sqrt's return value using %d which expects an int. Yet,
in actuality, sqrt() of course returns a double. The fact that
sqrt() returns a double, while the caller acts as if it returns
an int, will almost certainly prevent the program from working.

Why won't it work, exactly? It depends on the details of the
particular machine's function call and return mechanisms. We
haven't said which machine we're using, and we shouldn't have to
know the details of these mechanisms (they're the compiler's
worry, and to worry about them for us is one of the reasons we're
using a higher-level language like C in the first place), so we
can speak only in general terms. Perhaps the machine has one
general-purpose register which is designated as the location
where functions return values of integer types, and one
floating-point register which is designated as the location where
functions return values of floating-point types. If so, sqrt()
will write its return value to the floating-point return
register, and the calling code will read a garbage int value from
the general-purpose return register. Or, perhaps integer and
floating-point returns use the same locations. sqrt() will write
a floating-point value to the location, but the calling code will
incorrectly interpret it as an integer value. You'd then get
approximately the same result as you'd get from executing

double d = 12.;
int *ip = (int *)&d;
printf("%d\n", *ip);

In both cases, the *bit pattern* of the floating-point number is
interpreted as if it were an integer. Since the bit-level
representations of integer and floating-point data are invariably
different, confusing and inaccurate answers result. (Note that
in neither case -- the incorrect declaration of sqrt(), nor the
int/double pointer game -- does the compiler emit any code to do
double-to-int conversion. Any such conversions have been
effectively circumvented by the peculiarities of these two code
fragments. In the case of calling sqrt(), you'd get a proper
double-to-int conversion only if sqrt() were properly declared
as returning double, and the return value were assigned or cast
to an int.) Finally, suppose that values are returned on the
stack, but that sizeof(double) is greater than sizeof (int)
(as is usually the case). sqrt() will push a double-sized result
on the stack, but the caller will pop an int-sized one. Not only
will the caller print a garbage answer (interpreting those bits
it did pop as if they represented an int), but the shards of the
double remaining on the stack could screw later uses of the stack
up enough that the program could crash.

In the preceding example, the calling code was incorrect, because
it misdeclared the return value of the sqrt() function. We're
not allowed to choose what we want the return value of sqrt() to
be, because neither the defined return type of sqrt() (as fixed
by the Standard and long practice) nor the actual return type of
sqrt() (as implemented in the library provided with our compiler)
are under our control. Issuing an external declaration for
sqrt() declaring that it returns an int does not *make* it return
an int. (Nor does the misdeclaration instruct the compiler to
convert sqrt's return value from double to int; if the
declaration is wrong, how could the compiler even know that the
type to be converted from was double?) Abraham Lincoln used to
ask, "If we call a tail a leg, how many legs does a dog have?"
His answer was "Four -- calling it a leg doesn't make it one."

When we write an implementation of main() with a return type of
void, the situation is similar, but the roles are reversed.
Now, it is the caller that is fixed and beyond our control, and
that caller is assuming that main() returns an int. You may
imagine that somewhere (it's actually in the compiler vendor's
source for the C run-time library) there is some code which
looks something like this:

extern int main(int, char *[]);
int argc;
char *argv[MAXARGS];
int status;
...
status = main(argc, argv);
exit(status);

If the caller declares main() as returning int, and you define
main() as returning void, the declarations are mismatched,
just as the declarations of sqrt() were in the previous example.
In theory, the resulting program can fail in just the same sorts
of ways. But, to reiterate, here we can't fix the problem by
fixing the caller (because the caller is, er, fixed). Instead,
we have to fix main's declaration, which *is* under our control,
to match the caller's expectation.

Even if the program with the misdeclared main() "works" (that is,
compiles without error, and runs without crashing), it does
result in a garbage (random) exit status being returned to the
calling environment. You or your command invocation environment
may not be noticing that particular glitch right now, but it is a
glitch, and it may bite you later.

At one time, I had not gotten into the habit of making sure that
main() called exit() or returned an explicit value. (I wasn't
declaring main() as void, but I was getting the same sorts of
random exit status values.) Whenever I wrote a little program
(usually a special-purpose preprocessor) to automate some step in
the building of a large program, and stuck the program into one
of the productions in a Makefile, make would randomly abort the
build, saying that there had been an error, whenever the random
status returned by the little program was nonzero (i.e. not
EXIT_SUCCESS). Eventually, fixing enough of those drove home to
me the importance of always exiting with an appropriate, explicit
status, even in seemingly trivial programs.

Another place you'll notice the effect of a random exit status
is if you run a program with one in the background using a
job-control shell under Unix; when it finishes, you'll get a
message like "Done(1)" or "Exit 1" which, if you've gotten used
to the presence of the number indicating the presence of an
error, will mislead you into thinking that the command failed.

Yet other ways to see the results of particular exit statuses
(that is, to depend on their being deterministic) are when using
errorlevel in DOS batch files, or when using DCL in VMS.

> several books use int main() as examples and others use void main(void)

Indeed.

> main returns an int i assume?

Yes. More precisely, main is *supposed* to return an int; what
it actually returns is what you declare it to return (and what
your return statement(s), if any, say it returns). But if you
implement main as returning something other than what its caller
expects it to return, you run the risk of its not working
correctly.

In article <321cc6d4....@news2.microserve.net>,
sid...@lip.microserve.com goes on:


> Im curious why do i see void main(void) so much?

I honestly don't know.

The first few times I ever saw void main(), it was clear that
the programmer was trying to avoid warnings. The program

int main()
{
printf("Hello, world!\n");
exit(0);
}

does not return a value from main(), but it doesn't matter,
because control flow never falls off the end of main(), because
exit() never returns. But the compiler usually doesn't know
that exit() doesn't return, and may warn that "control reaches
end of int-valued function without returning a value." In the
program

int main()
{
printf("Hello, world!\n");
}

the compiler is likely to issue the same warning, and here it's
perfectly appropriate, but the programmer may not care, if the
program isn't ever to be executed in an environment where the
exit status matters. In either case, declaring main() as void
effectively shuts off that particular warning message, but at the
cost of making the program incorrect. (Indeed, some compilers
will issue other warnings when main() is misdeclared.)

It's because of this particular argument that the question
currently known as 11.12 in the FAQ list is worded the way it is,
but this line of reasoning is not sufficient to explain void
main()'s unaccountable popularity today. It's become some kind
of a meme plague: the "popular" textbooks all use it, so hordes
of unsuspecting C programmers learn it, and some of them go on to
teach classes or write more books which then spread the virus.
In fact, my initial supposition (outlined above) of why people
might write void main() is now not only insufficient, it's almost
completely forgotten! Today, when people who use void main() are
asked why they do, none of them ever mention shutting off
warnings about main() not returning a value. They all mumble
something like "but everyone else uses it" or "but it works on my
compiler" or (particularly in the case of misguided teachers and
textbook authors) "that way we don't have to introduce the full
complexity of return types right at first." (This last
justification is particularly specious, as we'll see.)

> what exactly is it saying? and why does it work ?

It tends to work (even though it doesn't have to and is not
guaranteed to) for a combination of three reasons:

1. Once upon a time, C did not have the void type.
Functions which did not return values were declared
(usually implicitly) as returning int, but did not
actually return values, and their callers did not use
the (nonexistent) return values. That's why, even today,
the ANSI Standard does not flatly prohibit falling off
the end of a non-void function without executing a return
statement, or issuing an expressionless return statement
within such a function. (The behavior is undefined only
if the caller tries to use the value, and never requires
a diagnostic. Good compilers will emit warnings.)
In the old days, it was up to the programmer to remember
which functions returned values and which didn't,
although this was of course one of the things which lint
checked (and, for those few who use it, still checks).

2. Partly because of #1, the actual low-level calling
mechanisms for void-valued and int-valued functions are
usually not different. A void-valued function simply
omits to place a value in the designated return value
location, and the caller doesn't try to fetch a value
from that location. In these cases, the worst thing
that happens when a function is incorrectly declared as
void is that the caller gets a garbage return value.
Misdeclaring main (or any function) as void will
typically only result in catastrophic failures if values
are returned on the stack: if the caller pops a value but
the caller didn't push one, the caller may instead have
popped something vital from the stack, such as a frame
pointer or return address, such that when the caller
later returns, chaos results.

3. Since so much code (including the examples in some compiler
manuals!) does misdeclare main() as void, compiler
vendors pretty much have to arrange that it works.
(Alas, this strategy is an "enabling" one; it allows the
users of void main() to perpetuate their rationalizations.)
Posters to comp.lang.c can arrogantly state that "Your
code is broken. Fix it.", but compiler vendors who
believe that "the customer is always right" cannot
(particularly if the vendor's offerings to date have
permitted void main()).

(As an aside, these three reasons conspire to require
nonstandard "pascal" keywords in compilers for environments where
code written in C must call libraries written in Pascal, or vice
versa. I gather that many Pascal compilers *do* use different
calling conventions for procedures and functions. If C
compilers didn't have to coddle broken code by making void-valued
and int-valued functions compatible, they could arrange that
void-valued functions were completely compatible with Pascal
procedures. Instead, a C program that calls a Pascal procedure
must typically declare it as

extern pascal void f();

or some such. Similar arguments apply to "fortran" and "basic"
keywords, and to fixed versus variable-length argument lists.)

> also if type int is implied and () is implied as an empty delaration (in ANSI)
> why not main() (although ive never seen it)...

"Plain" main() is in fact pretty common. When I teach
introductory C programming, I always leave the return type off
of main() in examples, because it's a distraction to have to
explain what a function's return type is at all at first,
particularly in a function like main() where it isn't obvious who
the caller is or what would happen to the return value. (Alas,
a certain amount of handwaving is still required if the main()
function includes an explicit return statement, as it must to
keep all compilers quiet.)

We can see, then, that an instructor or textbook author who
doesn't want to "introduce the full complexity of return types
right at first" could and should demonstrate main() without an
explicit return type, and that using void instead is doubly
counterproductive.

The situation is completely different, by the way, with respect
to a function's declared parameters. The declaration

extern main();

is an old-style declaration saying that main is a function taking
unspecified (but fixed) arguments. The *definition*

main()
{
}

, on the other hand, is an old-style definition saying that main
takes zero arguments. Since the caller (as we saw earlier) is
going to be passing two arguments to main(), how can we get away
with this misdeclaration?

The answer is that main's parameter list is a very definite wart
in Standard C. Anywhere else, if a function is called with a
number of arguments not matching its definition (and if the
function does not accept a variable-length argument list), the
behavior is undefined. In this one case, however, main() is
allowed to be defined as accepting either zero arguments or two,
of type int and char **. The reason for the wart is of course to
support old code, but a wart it is, and it may require some
compilers to treat a function named main specially.

> is return; implied return 0; ?

No. A return statement without an expression returns no defined
value, and is valid only in void-valued functions or in
functions where the caller doesn't use the return value.

Steve Summit
s...@eskimo.com

Tom Watson

unread,
Aug 23, 1996, 3:00:00 AM8/23/96
to

In article <321C43...@mr.insa-tlse.fr>, Lievre Ludovic
<lie...@mr.insa-tlse.fr> wrote:

> Zach Heilig wrote:
>
> >
> > > main returns an int i assume?
> >

> > That's exactly right.
> >
>
> What is the difference between
>
> void main (void)
> {
> exit (-1);
> }
>
>
> int main (void)
> {
>
> return (-1);
> }
>
> I think that both functions returns -1;
>

No, they don't. The first is defined incorrectly, as main should have a
return value of "int". The fact that it uses an "exit" function to return
to the environment is not relavent at all. In fact it doesn't even
"return" at all!!

The reason that some books seem to like defining "main" as "void" is to
eliminate a silly diagnostic that you haven't provided a return statement,
as in the first example above. The diagnostic is only a warning (it must
be), as the program:

#include <stdlib.h> /* This is needed for the 'exit' function */
int main (void) /* This is legal!! */
{
exit (0);
}

Is completely valid.

You see if the compiler is "smart" enough to think that the "main" routine
doesn't have a return value, it should be "smart" enough to understand the
"exit" function, and how it works, and how the "main" function is to be
defined. Anything less is just a wining compiler. Any book that thinks
that "main" should be declared as a "void" function is just WRONG!!

--
Tom Watson
t...@3do.com (Home: t...@johana.com)

Zefram

unread,
Aug 25, 1996, 3:00:00 AM8/25/96
to

Tanmoy Bhattacharya <tan...@qcd.lanl.gov> wrote:
>In article <4vhji6$p...@bbcnews.rd.bbc.co.uk>
>mi...@rd.bbc.co.uk (Mike Ellis) writes:
>ME: Formal parameter names must *not* be given in the declaration
>ME: (prototype) for a function, although they *must* be given in the
>ME: definition.

Wrong, according to the Standard. Parameter names are legal but
optional in a prototype. They are mandatory only in the defintion.
(In C++, and quite possibly C9X, they are also optional in the
defintion.)

>In fact, I belong to the opposite camp: I like giving the names of

>arguments in the headers: my declarations are identical to my

>definitions.

This is occasionally useful. When writing prototypes I usually don't
bother giving names to the parameters, but when there are several
parameters they can be useful to remind one of which parameter is
which, such as the following example from the GNU libc (paraphrased):

char *strstr(char const *__haystack, char const *__needle);

In the larger programs that I write, all the prototypes do in fact have
parameter names, but only because they are automatically generated by a
sed script extracting the start of each function definition. Merely
the ability to do this is, I think, sufficient reason to permit
parameter names in prototypes.

-zefram

Kurt Watzka

unread,
Aug 26, 1996, 3:00:00 AM8/26/96
to

mi...@rd.bbc.co.uk (Mike Ellis) writes:

>Mike Rubenstein (mik...@ix.netcom.com) wrote:
>: sid...@lip.microserve.com (Sid Lipkin) wrote:

>: > I see alot of reference to int main () being incorrect syntax..


>: > Ive gotten into the habit of doing it and would like to know what
>: > errors could pop up in my code from not voiding main.

>: int main() is correct, though many people prefer int main(void). This


>: is a matter of style -- they mean the same thing in a definition.

>Almost, but not quite.

>"int main();" declares main as a function returning an int and taking an
>unknown numbe of parameters - this is the old, K&R way of doing things
>and may one day disappear from ANSI/ISO C.

Mike Rubenstein was not talking about declarations, he was talking
about definitions. In a function definition, "main()", "main(void)",
and "int main(void)" mean the same thing. Really.

>When used as a definition the same distinction applies, and the same
>caveat about ISO one day removing support for the int main() construct
>applies. Be safe - if you're not using a brain-dead compiler, always
>use either "int main(void);" or "int main(int, char**);". Of course,
>that should be "int main(int argc, char **argv)" for the definition
>*only* - don't add the variable names to the declaration.

What will happen to me if I use parameter names in declarations? Is
there any reason, like, e.g., any words from the definition of the
C programming language, that

a) make "()" an obsolescent feature in a function definition,
b) or forbid the use of parameter names in a function declaration?

If you cannot come up with any sound reason for your claims, why do
you make them, esp. if you say that Mike Rubenstein is wrong in a
statement of fact about the C programming language?

Kurt

--
| Kurt Watzka Phone : +49-89-2180-6254
| wat...@stat.uni-muenchen.de

Dan Pop

unread,
Aug 26, 1996, 3:00:00 AM8/26/96
to

>mi...@rd.bbc.co.uk (Mike Ellis) writes:
>
>>Mike Rubenstein (mik...@ix.netcom.com) wrote:
>>: sid...@lip.microserve.com (Sid Lipkin) wrote:
>>: > I see alot of reference to int main () being incorrect syntax..
>>: > Ive gotten into the habit of doing it and would like to know what
>>: > errors could pop up in my code from not voiding main.
>
>>: int main() is correct, though many people prefer int main(void). This
>>: is a matter of style -- they mean the same thing in a definition.
>
>>Almost, but not quite.
>
>>"int main();" declares main as a function returning an int and taking an
>>unknown numbe of parameters - this is the old, K&R way of doing things
>>and may one day disappear from ANSI/ISO C.
>
>Mike Rubenstein was not talking about declarations, he was talking
>about definitions. In a function definition, "main()", "main(void)",
>and "int main(void)" mean the same thing. Really.

Almost. There is a small difference, however:

int main()
{
main(5); /* undefined behaviour */
}

int main(void)
{
main(5); /* a diagnostic is required */
}

For most intents and purposes, int main() and int main(void) are
equivalent in the definition of main, however.

C9X-based arguments are bogus in this discussion. Nobody knows how this
language will look like.

Bruce J Bronson

unread,
Aug 26, 1996, 3:00:00 AM8/26/96
to

While we are straining at knats. What about the the third argument to main!
After all you can pick up any C book and find the first two. But there is
a seldom talked about third.

Bruce

Danette & Murray Root

unread,
Aug 26, 1996, 3:00:00 AM8/26/96
to

On 26 Aug 96 12:54:44 GMT, bro...@potto.cig.mot.com (Bruce J Bronson)
wrote in comp.lang.c:

=>While we are straining at knats. What about the the third argument
to main!
=>After all you can pick up any C book and find the first two. But
there is
=>a seldom talked about third.

That's because the third is not part of ISO C. There is the MS
extension -

/* MS declaration from online help */
int main( int argc, char *argv[], char *envp[] )

where the third argument has something to do with the environment, but
even MS admits it's not part of the standard.

<><><><><><><><><><><><><><><><><><><><>

Wizard's First Rule:
People are stupid.
- Terry Goodkind

<><><><><><><><><><><><><><><><><><><><>


Zach Heilig

unread,
Aug 27, 1996, 3:00:00 AM8/27/96
to

Murra...@mindspring.com (Danette & Murray Root) writes:

> That's because the third is not part of ISO C. There is the MS
> extension -
>
> /* MS declaration from online help */
> int main( int argc, char *argv[], char *envp[] )
>
> where the third argument has something to do with the environment, but
> even MS admits it's not part of the standard.

Actually, it came from unix. Even in an appendix of the standard, it
notes that the third argument is a common extension (or was that in a
footnote?). So, even though the standard doesn't officially bless the
practice, the authors acknowledge that it is common.

Dan Pop

unread,
Aug 27, 1996, 3:00:00 AM8/27/96
to

In <bronson.841064084@potto> bro...@potto.cig.mot.com (Bruce J Bronson) writes:

>While we are straining at knats. What about the the third argument to main!

>After all you can pick up any C book and find the first two. But there is

>a seldom talked about third.

The third argument of main() is not a C feature. It's only a popular
extension which doesn't break the conformance of an implementation.

Strictly speaking, a program which defines main() as having three
arguments invokes undefined behaviour, just like void main().

Steve Summit

unread,
Aug 27, 1996, 3:00:00 AM8/27/96
to

In article <bronson.841064084@potto>, bro...@potto.cig.mot.com

(Bruce J Bronson) writes:
> While we are straining at knats. What about the the third argument to main!

That gnat has already been strained at, and is discussed
in the FAQ list.

pj

unread,
Aug 28, 1996, 3:00:00 AM8/28/96
to

Sid,

if you are not returning an int you should use void, but i dont think this
can adversly affect your programs.
Pete


Ethan

unread,
Aug 28, 1996, 3:00:00 AM8/28/96
to

Pete,

I don't know why you have to use 'int main()' ?
Please follow the book 'ANSI C programming language' by K & RC,I belive
you heard it.
It doesn't metion to use this syntax and I don't think it's illegal .
Another recommend book is 'The Art and Science of C' by Eric Roberts.

Regards,

Ethan.

The Amorphous Mass

unread,
Aug 28, 1996, 3:00:00 AM8/28/96
to

"pj" <pa...@neosoft.com> wrote:
>if you are not returning an int you should use void, but i dont think this
>can adversly affect your programs.

I s'pose there will always be one person like this...

1) When, why, and how would you "not return an int" from main()? Believe
it or not, most environments return something whether you tell them to or
not; if you don't explicitly return a value then they return garbage. This
might not affect your program, but it might do very funny things to the
program that called your program.

2) It can cause a link error on one platform (BC++ 4.52, compiling C),
and a compiler error on another (OpenVMS DEC C).

Needless to say, this and more is in the FAQ.

- James "Good candidates for exceptions are situations
james-r...@uiowa.edu that do not occur under normal circumstances."
-- Kevin J. Hopps

Zach Heilig

unread,
Aug 28, 1996, 3:00:00 AM8/28/96
to

"pj" <pa...@neosoft.com> writes:

> Sid,


>
> if you are not returning an int you should use void, but i dont think this
> can adversly affect your programs.

In the case of 'main()', you should NEVER use void as the return type.
It has all the problems you'd expect from declaring:

int sin(int);

and attempting to link against the real version (double sin(double);).
The fact that you don't see any ill effect doesn't change the fact
that it's wrong to use 'void main()'.

Lawrence Kirby

unread,
Aug 30, 1996, 3:00:00 AM8/30/96
to

In article <01bb948e$0d47d960$ac0c...@myoc.neosoft.com>
pa...@neosoft.com "pj" writes:

>Sid,
>
>if you are not returning an int you should use void, but i dont think this
>can adversly affect your programs.

That's fine except of course main() *must* return an int.

--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------

Szu-Wen Huang

unread,
Aug 30, 1996, 3:00:00 AM8/30/96
to

pj (pa...@neosoft.com) wrote:

: if you are not returning an int you should use void, but i dont think


: this can adversly affect your programs.

And you should at least read the FAQ before giving a wrong answer.

Kevin D. Quitt

unread,
Aug 30, 1996, 3:00:00 AM8/30/96
to

On 28 Aug 1996 03:13:04 GMT, "pj" <pa...@neosoft.com> wrote:

>Sid,


>
>if you are not returning an int you should use void, but i dont think this
>can adversly affect your programs.

void main() is specifically not allowed. Don't post if you don't know.

--
#include <standard_disclaimer.h>
_
Kevin D Quitt USA 91351-4454 96.37% of all statistics are made up
Per the FCA, this email address may not be added to any commercial mail list

Lawrence Kirby

unread,
Sep 1, 1996, 3:00:00 AM9/1/96
to

In article <5078nc$6...@news1.mnsinc.com> hu...@mnsinc.com "Szu-Wen Huang" writes:

>pj (pa...@neosoft.com) wrote:
>
>: if you are not returning an int you should use void, but i dont think


>: this can adversly affect your programs.
>

>And you should at least read the FAQ before giving a wrong answer.

Is he allowed to give a wrong answer after reading the FAQ? :-)

Kaz Kylheku

unread,
Sep 3, 1996, 3:00:00 AM9/3/96
to

In article <841409...@genesis.demon.co.uk>,

Lawrence Kirby <fr...@genesis.demon.co.uk> wrote:
>In article <01bb948e$0d47d960$ac0c...@myoc.neosoft.com>
> pa...@neosoft.com "pj" writes:
>
>>Sid,
>>
>>if you are not returning an int you should use void, but i dont think this
>>can adversly affect your programs.
>
>That's fine except of course main() *must* return an int.

Surely you mean that it must be declared as returning an int, but it may
actually not return an int at execution time in which case the exit status is
udefined, but the program isn't. The program may also not return at all, going
into an infinite service loop.

That begs the question. Does the standard require that all C programs halt,
lest they be considered non-conforming? I think not! :)

Lawrence Kirby

unread,
Sep 4, 1996, 3:00:00 AM9/4/96
to

In article <50huvp$7...@bcrkh13.bnr.ca>
k...@vision.crest.nt.com "Kaz Kylheku" writes:

>In article <841409...@genesis.demon.co.uk>,
>Lawrence Kirby <fr...@genesis.demon.co.uk> wrote:
>>In article <01bb948e$0d47d960$ac0c...@myoc.neosoft.com>
>> pa...@neosoft.com "pj" writes:
>>
>>>Sid,
>>>
>>>if you are not returning an int you should use void, but i dont think this
>>>can adversly affect your programs.
>>
>>That's fine except of course main() *must* return an int.
>
>Surely you mean that it must be declared as returning an int,

Yes, I do mean that.

>but it may
>actually not return an int at execution time in which case the exit status is
>udefined, but the program isn't.

Whenever a non-void function returns it returns a value. If that value is
not explicit in a return statement it is indeterminate and a C program
will invoke undefined behaviour if it tries to use it. The program startup
code isn't defined to be written in C and that is just specified as producing
an undefined termination status if the int value that main returns to it is
indeterminate.

>The program may also not return at all, going
>into an infinite service loop.

main is always a function that returns an int. That defines such things
as the calling sequence that the compiler uses. If you don't declare main
as returning int your program may not even run at all, even if the
compiler appears to compile it. Whether the flow of execution actually
returns is a different matter (it could call exit() for example) and
doesn't change the requirement that main() be declared as returning int.

>That begs the question. Does the standard require that all C programs halt,
>lest they be considered non-conforming? I think not! :)

The language doesn't specify how long a program should take to execute.

0 new messages