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

newbie question on understanding the main() function

6 views
Skip to first unread message

some

unread,
Feb 7, 2010, 8:11:14 PM2/7/10
to
If i write main like the following ways. Which one will compile and
why?

1. char * main();
2. char * main(int, char);
3. char * main(char);

I guess only first will(but, all three will flag a warning from the
compiler) because main in C needs argument names(not just argument
types) and cannot take a single argument(either zero or two
arguments). I tried this with GNU C compiler 4.3.2 on a Debian Linux
2.6.26.

I am a newbie so would appreciate any feedback if my understanding and
reasoning is correct.

Thanks

Ian Collins

unread,
Feb 7, 2010, 8:24:57 PM2/7/10
to
some wrote:
> If i write main like the following ways. Which one will compile and
> why?
>
> 1. char * main();
> 2. char * main(int, char);
> 3. char * main(char);
>
> I guess only first will(but, all three will flag a warning from the
> compiler) because main in C needs argument names(not just argument
> types) and cannot take a single argument(either zero or two
> arguments). I tried this with GNU C compiler 4.3.2 on a Debian Linux
> 2.6.26.

The first may compile, but on a hosted implementation such as yours main
returns int, not char*

--
Ian Collins

Seebs

unread,
Feb 7, 2010, 8:54:46 PM2/7/10
to
On 2010-02-08, some <s...@mailinator.com> wrote:
> If i write main like the following ways. Which one will compile and
> why?

Possibly none.

> 1. char * main();
> 2. char * main(int, char);
> 3. char * main(char);

> I guess only first will(but, all three will flag a warning from the
> compiler) because main in C needs argument names(not just argument
> types) and cannot take a single argument(either zero or two
> arguments). I tried this with GNU C compiler 4.3.2 on a Debian Linux
> 2.6.26.

You don't need argument names in a declaration, only in a definition;
since it ends with a semicolon, this is just a declaration. On the
other hand, you've declared the second argument with the wrong type.

However, the compiler is free to flag this declaration as incorrect,
because it knows that main() returns int.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Message has been deleted

Richard Heathfield

unread,
Feb 7, 2010, 9:31:17 PM2/7/10
to
some wrote:
> If i write main like the following ways. Which one will compile and
> why?
>
> 1. char * main();
> 2. char * main(int, char);
> 3. char * main(char);
>
> I guess only first will(but, all three will flag a warning from the
> compiler)

They are all wrong, but the compiler is not required to diagnose any of
them. This is one of those cases where the compiler is allowed to expect
you to know what you're doing; in such cases, if you /don't/ know what
you're doing, that's your problem, not the compiler's.

Note that the absence of argument names is not a problem because the
above are declarations, not definitions.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within

Eric Sosman

unread,
Feb 7, 2010, 10:01:14 PM2/7/10
to
On 2/7/2010 8:11 PM, some wrote:
> If i write main like the following ways. Which one will compile and
> why?
>
> 1. char * main();
> 2. char * main(int, char);
> 3. char * main(char);
>
> I guess only first will(but, all three will flag a warning from the
> compiler) because main in C needs argument names(not just argument
> types) and cannot take a single argument(either zero or two
> arguments). I tried this with GNU C compiler 4.3.2 on a Debian Linux
> 2.6.26.

All are likely to compile, because all are legal -- in a
free-standing program, where main() has no special significance.

In a hosted environment, though, all three are wrong. They
are likely to compile, but they are wrong nonetheless.

> I am a newbie so would appreciate any feedback if my understanding and
> reasoning is correct.

I can't tell about your understanding. Your reasoning, though,
is incorrect: "C needs argument names (not just argument types)" is
true for function definitions, but the three lines you've shown are
function declarations, *not* definitions. Right or wrong, all are
legal as declarations.

--
Eric Sosman
eso...@ieee-dot-org.invalid

some

unread,
Feb 7, 2010, 10:46:13 PM2/7/10
to
Thanks to all who responded to my question.

Richard Heathfield wrote:
> some wrote:
> > If i write main like the following ways. Which one will compile and
> > why?
> >
> > 1. char * main();
> > 2. char * main(int, char);
> > 3. char * main(char);
> >
> > I guess only first will(but, all three will flag a warning from the
> > compiler)
>
> They are all wrong, but the compiler is not required to diagnose any of
> them. This is one of those cases where the compiler is allowed to expect
> you to know what you're doing;

How do I know which cases are such(where compiler will not flag an
error, but actually
legal so don't evoke an error message from compiler)? I realize cases
where I am
allocating/deallocating memory, doing pointer arithmetic, returning
address of a local
variable from a function are cases where compiler will not balk as
they are legal, but are
wrong?

Which book should I read to know about such cases?

some

unread,
Feb 7, 2010, 10:49:49 PM2/7/10
to
Eric Sosman wrote:

> > If i write main like the following ways. Which one will compile and
> > why?
> >
> > 1. char * main();
> > 2. char * main(int, char);
> > 3. char * main(char);
> >
> > I guess only first will(but, all three will flag a warning from the
> > compiler) because main in C needs argument names(not just argument
> > types) and cannot take a single argument(either zero or two
> > arguments). I tried this with GNU C compiler 4.3.2 on a Debian Linux
> > 2.6.26.
>
> All are likely to compile, because all are legal -- in a
> free-standing program, where main() has no special significance.

How do I identify which code is legal(meaning compiler will not
produce any errors)? I thought all three were illegal, but was proved
wrong by the compiler.

> In a hosted environment, though, all three are wrong. They
> are likely to compile, but they are wrong nonetheless.
>
> > I am a newbie so would appreciate any feedback if my understanding and
> > reasoning is correct.
>
> I can't tell about your understanding. Your reasoning, though,
> is incorrect: "C needs argument names (not just argument types)" is
> true for function definitions, but the three lines you've shown are
> function declarations, *not* definitions. Right or wrong, all are
> legal as declarations.
>
> --
> Eric Sosman
> eso...@ieee-dot-org.invalid

Thanks for the clarification.

Richard Heathfield

unread,
Feb 8, 2010, 12:18:30 AM2/8/10
to
some wrote:
> Thanks to all who responded to my question.
>
> Richard Heathfield wrote:
>> some wrote:
>>> If i write main like the following ways. Which one will compile and
>>> why?
>>>
>>> 1. char * main();
>>> 2. char * main(int, char);
>>> 3. char * main(char);
>>>
>>> I guess only first will(but, all three will flag a warning from the
>>> compiler)
>> They are all wrong, but the compiler is not required to diagnose any of
>> them. This is one of those cases where the compiler is allowed to expect
>> you to know what you're doing;
>
> How do I know which cases are such(where compiler will not flag an
> error, but actually
> legal so don't evoke an error message from compiler)?

That's actually a very good question. Unfortunately, the only answer I
can come up with is "know the language". That isn't a very satisfactory
answer; it would be much more convenient if the compiler could catch all
our mistakes. Nevertheless, there are situations which the compiler is
not expected to be able to deal with. In "Standardese" (the language of
the C definition), such situations are described as "undefined".

It is worth getting hold of a copy of the Standard (free drafts are
available online), and spending a happy few hours searching the text for
"undefined". You may be surprised at just how many situations it covers.
For example, the behaviour of:

int i = INT_MAX;
++i;

is undefined. You'd think it would just wrap, wouldn't you? Well, it
might. Or it might not. And the compiler isn't obliged to catch
"overflow", as it's called. Why not? Well, let's imagine the user enters
a value at the keyboard, and your code adds 1 to it. Not an unreasonable
thing to want to do, is it? But if the user happens to enter the value
corresponding to INT_MAX, then you have overflow. The compiler can't
know that the user is going to enter that value. I suppose you could
have it flag every single addition, just in case - but that would
generate a vast number of false positives, which would waste far more
time than it saves.

So the answer really is "know the language". Know what's allowed, what
isn't, and what's on the edge. Avoid what isn't allowed, and try to keep
off the edge as much as you can.

This newsgroup excels at helping you to understand what's allowed and
what isn't, but there is no real substitute for getting and reading, and
re-re-re-re-re-re-re-re-re-reading, a copy of the Standard.

<snip>

santosh

unread,
Feb 8, 2010, 2:50:28 AM2/8/10
to
some wrote:
<snip>

> How do I know which cases are such(where compiler will not flag an error, but actually legal so don't evoke an
> error message from compiler)? I realize cases where I am allocating/deallocating memory, doing pointer arithmetic,
> returning address of a local variable from a function are cases where compiler will not balk as they are legal, but
> are wrong?
>
> Which book should I read to know about such cases?

Since you claim to be a beginner, rather than trying to figure the
Standard, I'd recommend you to pick up a copy of The C Programming
Language 2nd Ed. by Kernighan & Ritchie. It's lucid, authoritative and
fairly comprehensive from the POV of the C90 standard. It's also
suitable as a "first book" to learn C from.

One other often recommended book would be C: A Reference Manual by
Harbison & Steele. It's meant to comprehensively cover the latest
version of Standard C, but it's not suitable for learning C from.

<http://cm.bell-labs.com/cm/cs/cbook/>
<http://www.careferencemanual.com/>

Seebs

unread,
Feb 8, 2010, 3:05:19 AM2/8/10
to
On 2010-02-08, santosh <santo...@gmail.com> wrote:
><http://cm.bell-labs.com/cm/cs/cbook/>
><http://www.careferencemanual.com/>

Let me tack on my own recommendation:

http://knking.com/books/c/

This is my current favorite book on C. I actually think it's a better
teaching book than K&R.

Phred Phungus

unread,
Feb 8, 2010, 6:10:21 AM2/8/10
to
Richard Heathfield wrote:
> some wrote:
>> If i write main like the following ways. Which one will compile and
>> why?
>>
>> 1. char * main();
>> 2. char * main(int, char);
>> 3. char * main(char);
>>
>> I guess only first will(but, all three will flag a warning from the
>> compiler)
>
> They are all wrong, but the compiler is not required to diagnose any of
> them. This is one of those cases where the compiler is allowed to expect
> you to know what you're doing; in such cases, if you /don't/ know what
> you're doing, that's your problem, not the compiler's.
>
> Note that the absence of argument names is not a problem because the
> above are declarations, not definitions.
>


You're sure that the compiler isn't bothered by the lack of the ** in char?

I would think that these would traouble:

int main(int, char);
int main(char);

Philip Potter

unread,
Feb 8, 2010, 6:40:51 AM2/8/10
to

A good starting place would be to read through the comp.lang.c FAQ at
http://c-faq.com/. There's a lot of discussion of different types of
not-well-defined-but-not-necessarily-error-producing code there to get
you started; particularly the sections on expressions, pointers and
memory allocation, but elsewhere too.

However, while it is a good resource, it is not enough on its own; it
must be read *in addition* to a good textbook such as those recommended
by santosh.

Also, if you haven't done so already, you should find out how to turn on
your compiler's stricter error checking modes. You mentioned you were
using gcc, so try:

gcc -ansi -pedantic -Wall -Wextra -o<destination> <source>

-ansi turns off extensions which are not allowed by the Standard
-pedantic emits all diagnostics (warnings) required by the Standard
-Wall turns on lots more warnings
-Wextra turns on even more warnings [can use -W instead of -Wextra]

In this case, -Wall enables the -Wmain warning:
-Wmain
Warn if the type of main is suspicious. main should be a function
with external linkage, returning int, taking either zero arguments,
two, or three arguments of appropriate types. This warning is
enabled by -Wall.

[If you're interested, the three-argument main() mentioned is a
nonstandard extension which (I think) provides a pointer to a data
structure representing the environment. Rather than using this
extension, you can just use the (standard, porable) getenv() function
instead.]

Phil

Richard Heathfield

unread,
Feb 8, 2010, 6:50:23 AM2/8/10
to
Phred Phungus wrote:

<snip>

> You're sure that the compiler isn't bothered by the lack of the ** in char?

The implementation is allowed, but not required, to be bothered.

santosh

unread,
Feb 8, 2010, 6:56:25 AM2/8/10
to
Philip Potter wrote:
> On 08/02/2010 03:46, some wrote:
[...]

I would also suggest turning on the switch[es] for optimisations
during compiling. The analysis the compiler does for optimisation
often points out many suspicious constructs like unusued/uninitialised
variables, dead code and so on, which might be of interest to those
learning to program. Look for the 'O' switch, or a variant, under most
compilers.

Ben Bacarisse

unread,
Feb 8, 2010, 8:27:19 AM2/8/10
to
some <s...@mailinator.com> writes:

> Eric Sosman wrote:
>
>> > If i write main like the following ways. Which one will compile and
>> > why?
>> >
>> > 1. char * main();
>> > 2. char * main(int, char);
>> > 3. char * main(char);
>> >
>> > I guess only first will(but, all three will flag a warning from the
>> > compiler) because main in C needs argument names(not just argument
>> > types) and cannot take a single argument(either zero or two
>> > arguments). I tried this with GNU C compiler 4.3.2 on a Debian Linux
>> > 2.6.26.
>>
>> All are likely to compile, because all are legal -- in a
>> free-standing program, where main() has no special significance.
>
> How do I identify which code is legal(meaning compiler will not
> produce any errors)? I thought all three were illegal, but was proved
> wrong by the compiler.

It is not very useful to define legal/illegal in terms of what message
you get from a compiler. For one thing, different compiler options
can produce wildly differing quantities of diagnostics from the same
code. For another, the standard does not require an implementation to
"produce errors". All it does is list some things that must give rise
to "a diagnostic" while at the same time permitting any other
diagnostics that the implementation may like to produce.

The closest you can get to what you describe is to avoid all those
errors that are described as "constraint violations" by the standard.
These must be diagnosed by the compiler. An incorrect definition of
main is not a constraint violation (I am not sure why, but there it
is) so the compiler can be silent about it if it chooses to be.

<snip>
--
Ben.

Eric Sosman

unread,
Feb 8, 2010, 8:53:19 AM2/8/10
to
On 2/7/2010 10:49 PM, some wrote:
> Eric Sosman wrote:
>
>>> If i write main like the following ways. Which one will compile and
>>> why?
>>>
>>> 1. char * main();
>>> 2. char * main(int, char);
>>> 3. char * main(char);
>>>
>>> I guess only first will(but, all three will flag a warning from the
>>> compiler) because main in C needs argument names(not just argument
>>> types) and cannot take a single argument(either zero or two
>>> arguments). I tried this with GNU C compiler 4.3.2 on a Debian Linux
>>> 2.6.26.
>>
>> All are likely to compile, because all are legal -- in a
>> free-standing program, where main() has no special significance.
>
> How do I identify which code is legal(meaning compiler will not
> produce any errors)? I thought all three were illegal, but was proved
> wrong by the compiler.

The compiler cannot decree what is "legal" and "illegal,"
because in most jurisdictions the compiler does not have the
force of law. The compiler cannot fine you, throw you in jail,
or lop off your right hand on account of any code you might
put before it.

That's a bit silly, of course, but it's intended to make a
more serious point: The definition of C is not written with
"thou shalt" and "thou shalt not," but more along the lines of
a contract or agreement: "If thou dost X, the implementation
shall respond as Y."

There are two parties to this contract, and each must keep
up his side of the bargain for the agreement to have meaning.
Your choices of X are restricted to things that the agreement
covers: If you do X' instead, where X' is not part of the agreed
universe of possibilities, the implementation is no longer bound
to keep up its side of the agreement you've abrogated.

Some kinds of out-of-bounds X' require the implementation to
issue a diagnostic message. The implementation may then reject
the program altogether, or may accept it and try to run it anyhow.
(Even if it runs, though, the agreement has been violated and no
longer governs what the program might do.) Some other kinds of
invalid X' produce "undefined behavior," meaning that they may
or may not elicit diagnostics, and they may or may not do what
you hoped they would. ABSENCE OF DIAGNOSTICS IS NOT CORRECTNESS.

To the point at hand: In a hosted environment, part of your
side of the agreement is to provide a main() function in one of
two prescribed styles. Your main() can take no arguments, or it
can take one int and one char** argument; in both cases, it must
be defined as returning an int value. If you fail to provide a
main(), or if you provide a main() of some other flavor, you have
provided an X' and the agreement no longer holds. The compiler
may complain and reject your code, or may complain and accept it,
or may accept it in silence -- but in the latter cases, C itself
does not define what your program may or may not do.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Philip Potter

unread,
Feb 8, 2010, 9:44:51 AM2/8/10
to
On 08/02/2010 13:27, Ben Bacarisse wrote:
> An incorrect definition of
> main is not a constraint violation (I am not sure why, but there it
> is) so the compiler can be silent about it if it chooses to be.

One reason might be that implementations are free to allow alternative
definitions of main() other than int main(void) and int main(int,
char**). For example, the fairly widely used
int main(int argc, char **argv, char **envp)
would violate any constraint requiring main to be one of the two
standard prototypes.

I don't know how old envp is. I used it once or twice in the 90s in
Turbo C. If it is old enough to be pre-Standard, it may have influenced
the Committee not to make a reasonably common extension a constraint
violation.

Phil

Ben Bacarisse

unread,
Feb 8, 2010, 12:19:02 PM2/8/10
to
Philip Potter <p...@doc.ic.ac.uk> writes:

> On 08/02/2010 13:27, Ben Bacarisse wrote:
>> An incorrect definition of
>> main is not a constraint violation (I am not sure why, but there it
>> is) so the compiler can be silent about it if it chooses to be.
>
> One reason might be that implementations are free to allow alternative
> definitions of main() other than int main(void) and int main(int,
> char**). For example, the fairly widely used
> int main(int argc, char **argv, char **envp)
> would violate any constraint requiring main to be one of the two
> standard prototypes.

I'd have thought that the wording could permit implementation-defined
alternatives (without a diagnostic) but I take your point.

Another way would be to do what is done with constant expressions --
extensions are allowed but anything that is not a constant expression
as defined by the standard must be diagnosed. Helpful when writing
for portability.

It hardly matters. main can appear only once so it is one of the
simplest things to check when moving from one system to another.

> I don't know how old envp is. I used it once or twice in the 90s in
> Turbo C. If it is old enough to be pre-Standard, it may have influenced
> the Committee not to make a reasonably common extension a constraint
> violation.

It is certainly pre-standard. Of course, pre-standard it was usually
written main(argc, argv, envp) int argc; char **argv, **evnp; {...}

So many changes happened in the C90 standard that I doubt an extra
diagnostic would be considered much trouble but that is a largely
unfounded opinion!

--
Ben.

Seebs

unread,
Feb 8, 2010, 12:26:58 PM2/8/10
to
On 2010-02-08, Philip Potter <p...@doc.ic.ac.uk> wrote:
> One reason might be that implementations are free to allow alternative
> definitions of main() other than int main(void) and int main(int,
> char**). For example, the fairly widely used
> int main(int argc, char **argv, char **envp)
> would violate any constraint requiring main to be one of the two
> standard prototypes.

When I submitted my hack to gcc to warn for incorrect main, I made that
one a pedantic warning rather than a regular warning. The reason is that
it predaces the standard by a LONG margin... But is considered
obsolescent.

> I don't know how old envp is. I used it once or twice in the 90s in
> Turbo C. If it is old enough to be pre-Standard, it may have influenced
> the Committee not to make a reasonably common extension a constraint
> violation.

That may be. Meanwhile, the POSIX folks went ahead and standardized
"extern char **environ;" as a superior replacement. ("Superior" is a
matter of potential dispute, I guess.)

some

unread,
Feb 8, 2010, 8:19:19 PM2/8/10
to
Thanks to all who responded.

I will turn on the warnings as you suggest and use lint if it
is available on my system to catch such mistakes which are legal
but lead to undefined behavior.

I will also go through the Standard, K&R
and Harrison Steele's Reference manual. The Harrison Steele's C
Reference manual
book looks more difficult to understand than the K&R
and the examples at the end of each chapter are certainly tougher for
me than K&R.
Perhaps, I am too dense as I hear high school students and college
freshmen solve them easily
I need some sharpening of wits.

Thanks again to all who responded.

Tim Rentsch

unread,
Mar 2, 2010, 4:12:27 PM3/2/10
to
Ben Bacarisse <ben.u...@bsb.me.uk> writes:

> Philip Potter <p...@doc.ic.ac.uk> writes:
>
>> On 08/02/2010 13:27, Ben Bacarisse wrote:
>>> An incorrect definition of
>>> main is not a constraint violation (I am not sure why, but there it
>>> is) so the compiler can be silent about it if it chooses to be.
>>
>> One reason might be that implementations are free to allow alternative
>> definitions of main() other than int main(void) and int main(int,
>> char**). For example, the fairly widely used
>> int main(int argc, char **argv, char **envp)
>> would violate any constraint requiring main to be one of the two
>> standard prototypes.
>
> I'd have thought that the wording could permit implementation-defined
> alternatives (without a diagnostic) but I take your point.
>
> Another way would be to do what is done with constant expressions --
> extensions are allowed but anything that is not a constant expression

> as defined by the standard must be diagnosed. [snip]

As far as I know implementation-specific constant expressions are
not required to be given a diagnostic (assuming 6.6p3 isn't
violated), since 6.6p10 explicitly and specifically allows them
as constant expressions. Do have a supporting citation? No
constraints are violated as far as I know.

Ben Bacarisse

unread,
Mar 2, 2010, 5:00:29 PM3/2/10
to
Tim Rentsch <t...@x-alumni2.alumni.caltech.edu> writes:

> Ben Bacarisse <ben.u...@bsb.me.uk> writes:
<snip>


>> Another way would be to do what is done with constant expressions --
>> extensions are allowed but anything that is not a constant expression
>> as defined by the standard must be diagnosed. [snip]
>
> As far as I know implementation-specific constant expressions are
> not required to be given a diagnostic (assuming 6.6p3 isn't
> violated), since 6.6p10 explicitly and specifically allows them
> as constant expressions. Do have a supporting citation?

No. I was miss-remembering something, though I don't know what exactly.

--
Ben.

0 new messages