By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,636 Members | 1,915 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,636 IT Pros & Developers. It's quick & easy.

Is this legal C?

P: n/a
Max
This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?

#define main()
int main
#define mainbody () { return 0; }
mainbody

Jun 27 '08 #1
Share this Question
Share on Google+
36 Replies


P: n/a
Max wrote:
This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?
Yes. Yes.
#define main()
int main
#define mainbody () { return 0; }
mainbody
It's as legal as

int main(){return 0;}

is.
--
pete
Jun 27 '08 #2

P: n/a
pete <pf*****@mindspring.comwrites:
Max wrote:
This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?

Yes. Yes.
#define main()
int main
#define mainbody () { return 0; }
mainbody

It's as legal as

int main(){return 0;}

is.
There's a fairly subtle argument that "int main()" is not actually
required to be supported, but for all practical purposes it's ok.
"int main(void)" is better, though.

Note that "main" is defined as a function-like macro, and "mainbody"
is defined as an object-like macro.

Compiling the code and/or examining the preprocessor output (assuming
your compiler supports this) won't definitively answer the question,
but it will give some good hints.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 28 '08 #3

P: n/a
Keith Thompson said:

<snip>
There's a fairly subtle argument that "int main()" is not actually
required to be supported,
I remember that this has come up before. I wasn't completely convinced
then, and I'm not completely convinced now.

A function definition that has no parameter list takes no parameters, and
is thus precisely equivalent to int main(void) in semantic terms. (Note
that we're not talking about mere definitions here.)

Since the Standard only requires of main that it be equivalent to int
main(void) or int main(int argc, char **argv), and since int main() is
equivalent to int main(void), it seems to me that int main() is perfectly
acceptable - to the compiler, at least, even though the stylist might
object.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 28 '08 #4

P: n/a
Keith Thompson wrote:
pete <pf*****@mindspring.comwrites:
>Max wrote:
>>This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?
Yes. Yes.
>>#define main()
int main
#define mainbody () { return 0; }
mainbody
It's as legal as

int main(){return 0;}

is.

There's a fairly subtle argument that "int main()" is not actually
required to be supported, but for all practical purposes it's ok.
"int main(void)" is better, though.

Note that "main" is defined as a function-like macro, and "mainbody"
is defined as an object-like macro.
main isn't defined as a macro.
main() is defined as a macro.

--
pete
Jun 28 '08 #5

P: n/a
In article <Kr******************************@bt.com>,
Richard Heathfield <rj*@see.sig.invalidwrote:
>Keith Thompson said:

<snip>
>There's a fairly subtle argument that "int main()" is not actually
required to be supported,

I remember that this has come up before. I wasn't completely convinced
then, and I'm not completely convinced now.

A function definition that has no parameter list takes no parameters, and
is thus precisely equivalent to int main(void) in semantic terms. (Note
that we're not talking about mere definitions here.)

Since the Standard only requires of main that it be equivalent to int
main(void) or int main(int argc, char **argv), and since int main() is
equivalent to int main(void), it seems to me that int main() is perfectly
acceptable - to the compiler, at least, even though the stylist might
object.
Nice to see clc regulars returning to their home territory.

Coming soon: Casting the return value of malloc().

Jun 28 '08 #6

P: n/a
Max
pete wrote:
>Max wrote:
>This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?

Yes. Yes.
Thanks.
>#define main()
int main
#define mainbody () { return 0; }
mainbody

It's as legal as

int main(){return 0;}

is.
Jun 28 '08 #7

P: n/a
Richard Heathfield said:

<snip>
A function definition that has no parameter list takes no parameters, and
is thus precisely equivalent to int main(void) in semantic terms.
So far, so good...
(Note that we're not talking about mere definitions here.)
s/fini/clara/sigh!
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 28 '08 #8

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
Keith Thompson said:
<snip>
There's a fairly subtle argument that "int main()" is not actually
required to be supported,

I remember that this has come up before. I wasn't completely convinced
then, and I'm not completely convinced now.

A function definition that has no parameter list takes no parameters, and
is thus precisely equivalent to int main(void) in semantic terms. (Note
that we're not talking about mere definitions here.)

Since the Standard only requires of main that it be equivalent to int
main(void) or int main(int argc, char **argv), and since int main() is
equivalent to int main(void), it seems to me that int main() is perfectly
acceptable - to the compiler, at least, even though the stylist might
object.

<snip>
Reference: C99 5.1.2.2.1 Program startup

For this definition:

int main() { return 0; }

to be valid (by "valid" here, I mean that an implementation is
required to support it with well-defined behavior), it must be
"equivalent" to this definition, which is undeniably valid:

int main(void) { return 0; }

It's equivalent by itself, when considered only as a self-contained
function definition. However, the definition also provides a
*declaration*. I assert that the two definitions are *not*
equivalent, because they provide non-equivalent declarations.

Assume an implementation that does accept "int main() { return 0; }"
with the obvious meaning (this is allowed by the "or in some other
implementation-defined manner" clause if not by the "or equivalent"
clause). Or, if you prefer, assume that "int main() { return 0; }" is
valid. Then this program:

int main() { return 0; }

void foo(void) { main(42); }

is valid (the declaration of main requires an unspecified number and
type of arguments; the call to main would invoke undefined behavior if
it were executed, but it never is). But this program:

int main(void) { return 0; }

void foo(void) { main(42); }

violates the constraint in C99 6.5.2.2p2.

Therefore, a definition using "int main()" is not equivalent to one
using "int main(void)", and thus an implementation needn't support it.

Note that, assuming my reasoning is correct, "int main()" doesn't
violate any constraint. A program that uses it merely invokes
undefined behavior. As it happens, every implementation I know of
responds to this undefined behavior by quietly accepting the
definition.

I'm not convinced that this was the intent, and I'd be unsurprised to
find that the members of the committee either intended "int main()" to
be valid, or just didn't think about it.

Implementers can avoid the issue by accepting "int main()", and
programmers can avoid the issue by using not using "int main()", so
it's not a huge deal either way.

I see I posted a similar question to comp.std.c last July,
subject "Is 'int main() { /* ... */ }' valid?":

http://groups.google.com/group/comp....630179750145a9

but re-reading that thread I see I was actually asking about a
different subtle issue.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 28 '08 #9

P: n/a
pete <pf*****@mindspring.comwrites:
Keith Thompson wrote:
pete <pf*****@mindspring.comwrites:
Max wrote:
This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?
Yes. Yes.

#define main()
int main
#define mainbody () { return 0; }
mainbody
It's as legal as

int main(){return 0;}

is.
There's a fairly subtle argument that "int main()" is not actually
required to be supported, but for all practical purposes it's ok.
"int main(void)" is better, though.
Note that "main" is defined as a function-like macro, and "mainbody"
is defined as an object-like macro.

main isn't defined as a macro.
main() is defined as a macro.
I understand what you mean, but a macro name is an identifier; the
parentheses aren't part of the name.

See also the standard's definitions of "object-like macro" and
"function-like macro".

#include <stdio.h>

void Keith_Is_Right(void);

#define main()
int main
#define mainbody () { Keith_Is_Right(); return 0; }
mainbody

void Keith_Is_Right(void)
{
#ifdef main
puts("Yes, main is defined as a macro.");
#else
puts("Never mind.");
#endif
}

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 28 '08 #10

P: n/a
Keith Thompson wrote:
pete <pf*****@mindspring.comwrites:
>Keith Thompson wrote:
>>pete <pf*****@mindspring.comwrites:
Max wrote:
This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?
Yes. Yes.

#define main()
int main
#define mainbody () { return 0; }
mainbody
It's as legal as

int main(){return 0;}

is.
There's a fairly subtle argument that "int main()" is not actually
required to be supported, but for all practical purposes it's ok.
"int main(void)" is better, though.
Note that "main" is defined as a function-like macro, and "mainbody"
is defined as an object-like macro.
main isn't defined as a macro.
main() is defined as a macro.

I understand what you mean, but a macro name is an identifier; the
parentheses aren't part of the name.

See also the standard's definitions of "object-like macro" and
"function-like macro".

#include <stdio.h>

void Keith_Is_Right(void);

#define main()
int main
#define mainbody () { Keith_Is_Right(); return 0; }
mainbody

void Keith_Is_Right(void)
{
#ifdef main
puts("Yes, main is defined as a macro.");
#else
puts("Never mind.");
#endif
}
Yes, main is defined as a macro.

Thank you.

--
pete
Jun 28 '08 #11

P: n/a
Keith Thompson said:
Richard Heathfield <rj*@see.sig.invalidwrites:
>Keith Thompson said:
<snip>
There's a fairly subtle argument that "int main()" is not actually
required to be supported,

I remember that this has come up before. I wasn't completely convinced
then, and I'm not completely convinced now.

A function definition that has no parameter list takes no parameters,
and is thus precisely equivalent to int main(void) in semantic terms.
(Note that we're not talking about mere definitions here.)

Since the Standard only requires of main that it be equivalent to int
main(void) or int main(int argc, char **argv), and since int main() is
equivalent to int main(void), it seems to me that int main() is
perfectly acceptable - to the compiler, at least, even though the
stylist might object.

<snip>

Reference: C99 5.1.2.2.1 Program startup

For this definition:

int main() { return 0; }

to be valid (by "valid" here, I mean that an implementation is
required to support it with well-defined behavior), it must be
"equivalent" to this definition, which is undeniably valid:

int main(void) { return 0; }

It's equivalent by itself, when considered only as a self-contained
function definition. However, the definition also provides a
*declaration*. I assert that the two definitions are *not*
equivalent, because they provide non-equivalent declarations.
I disagree, because of 3.5.4.3 (C89):

"An identifier list declares only the identifiers of the parameters of the
function. An empty list in a function declarator that is part of a
function definition specifies that the function has no parameters. The
empty list in a function declarator that is not part of a function
definition specifies that no information about the number or types of the
parameters is supplied."

The wording is almost identical in C99:

6.7.5.3(14) (C99):
"An identifier list declares only the identifiers of the parameters of the
function. An empty list in a function declarator that is part of a
definition of that function specifies that the function has no parameters.
The empty list in a function declarator that is not part of a definition
of that function specifies that no information about the number or types
of the parameters is supplied."

So the empty list in int main() { return 0; } specifies that the function
has no parameters, which means that it is semantically equivalent to int
main(void), QED.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 28 '08 #12

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
Keith Thompson said:
[...]
Reference: C99 5.1.2.2.1 Program startup

For this definition:

int main() { return 0; }

to be valid (by "valid" here, I mean that an implementation is
required to support it with well-defined behavior), it must be
"equivalent" to this definition, which is undeniably valid:

int main(void) { return 0; }

It's equivalent by itself, when considered only as a self-contained
function definition. However, the definition also provides a
*declaration*. I assert that the two definitions are *not*
equivalent, because they provide non-equivalent declarations.

I disagree, because of 3.5.4.3 (C89):

"An identifier list declares only the identifiers of the parameters of the
function. An empty list in a function declarator that is part of a
function definition specifies that the function has no parameters. The
empty list in a function declarator that is not part of a function
definition specifies that no information about the number or types of the
parameters is supplied."

The wording is almost identical in C99:

6.7.5.3(14) (C99):
"An identifier list declares only the identifiers of the parameters of the
function. An empty list in a function declarator that is part of a
definition of that function specifies that the function has no parameters.
The empty list in a function declarator that is not part of a definition
of that function specifies that no information about the number or types
of the parameters is supplied."

So the empty list in int main() { return 0; } specifies that the function
has no parameters, which means that it is semantically equivalent to int
main(void), QED.
Yes, the empty list specifies, for purposes of the definition (the
body of the function), that the function has no parameters. So the
two definitions are equivalent in what they say about main's
parameters.

But they are not equivalent in other ways.

An empty list doesn't specify that a caller must pass no arguments,
because it doesn't provide a prototype.

Given "int main(void) { ... }", an attempt to call "main(42)" violates
a constraint. Given "int main(void) { ... }", such a call does not
violate a constraint (though it does invoke undefined behavior).

A prototype is not equivalent to the absence of a prototype.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 28 '08 #13

P: n/a
Keith Thompson said:

<snip>
Yes, the empty list specifies, for purposes of the definition (the
body of the function), that the function has no parameters. So the
two definitions are equivalent in what they say about main's
parameters.

But they are not equivalent in other ways.

An empty list doesn't specify that a caller must pass no arguments,
because it doesn't provide a prototype.

Given "int main(void) { ... }", an attempt to call "main(42)" violates
a constraint. Given "int main(void) { ... }", such a call does not
violate a constraint (though it does invoke undefined behavior).

A prototype is not equivalent to the absence of a prototype.
Thank you. I don't think this loophole in the Standard was
intentional, but it certainly does seem to be present. At
least, I can't see any wiggle-room that might invalidate
your argument.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 28 '08 #14

P: n/a
Max wrote:
) This was asked in a C test. Is the following code legal C?
) Is it legal in C90? C99?
)
) #define main()
) int main
) #define mainbody () { return 0; }
) mainbody

Correct me if I'm wrong, but after preprocessing, doesn't this expand to:

---
int main

{ return 0; }
---

Which is missing the parens after main, and so is illegal ?
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
Jun 28 '08 #15

P: n/a
Willem <wi****@stack.nlwrote:
Max wrote:
) This was asked in a C test. Is the following code legal C?
) Is it legal in C90? C99?
)
) #define main()
) int main
) #define mainbody () { return 0; }
) mainbody

Correct me if I'm wrong, but after preprocessing, doesn't this expand to:

---
int main

{ return 0; }
---

Which is missing the parens after main, and so is illegal ?
You are wrong. 'main' is defined as a function-like macro taking no arguments
and expanding to an empty string. The 'main' in "int main" does not match an
invocation of this macro and is thus not replaced.
'mainbody' on the other hand is an object-like macro which is defined as "()
{ return 0; }".

(It makes a great deal of difference if there is a space or not between the
macro name and a '(' when defining a macro.)

After preprocessing it should thus expand to:

---

int main

() { return 0; }
---

Which is of course equivalent to
---
int main() { return 0; }
---
which is quite legal.
--
<Insert your favourite quote here.>
Erik Trulsson
er******@student.uu.se
Jun 28 '08 #16

P: n/a
pete schrieb:
Max wrote:
>This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?

Yes. Yes.
>#define main()
int main
#define mainbody () { return 0; }
mainbody
Must be some gcc extension. This compiles not even with LCC-WIN32:

lc -ansic -O -c main.c
Error main.c: 4 Syntax error; missing semicolon before `mainbody'
Warning main.c: 4 no type specified. Defaulting to int
Error main.c: 5 Syntax error; missing semicolon before `end of input'
2 errors, 1 warning
1 error
>
It's as legal as

int main(){return 0;}

is.
Jun 28 '08 #17

P: n/a
Hans Schneider wrote:
pete schrieb:
>Max wrote:
>>This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?
Yes. Yes.
>>#define main()
int main
#define mainbody () { return 0; }
mainbody

Must be some gcc extension. This compiles not even with LCC-WIN32:
Is that "sarcasm"?
lc -ansic -O -c main.c
Error main.c: 4 Syntax error; missing semicolon before `mainbody'
Warning main.c: 4 no type specified. Defaulting to int
Error main.c: 5 Syntax error; missing semicolon before `end of input'
2 errors, 1 warning
1 error
>It's as legal as

int main(){return 0;}

is.

--
pete
Jun 28 '08 #18

P: n/a
Hans Schneider <ha**@localhost.localdomainwrites:
pete schrieb:
>Max wrote:
>>This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?

Yes. Yes.
>>#define main()
int main
#define mainbody () { return 0; }
mainbody

Must be some gcc extension.
The reference is to check the standard, not to try various
implementations. The standard is clear that main does not get
expanded and that mainbody should be because mainbody is an
object-like macro, not a function-like one.
This compiles not even with LCC-WIN32:
Then file a bug report if you are interested. lcc-win32 fails to see
mainbody as a macro that should be expanded. If we remove the
entirely unused #define main() the lcc-win32 gets it right. That
unused definition of main is throwing it. I can guess why -- the
pre-processor must look to see if 'main' is followed by '(', and this
must be done without expanding macros. However, having seen that
'main' is not followed by a '(', the token that was looked at needs to
checked to see if it *does* expand. A simple example of the bug is
this:

#define F()
#define M
F M

which should expand to 'F' but with lcc-win32 you get 'F M'.

--
Ben.
Jun 28 '08 #19

P: n/a
Hans Schneider wrote:
pete schrieb:
>Max wrote:
>>This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?

Yes. Yes.
>>#define main()
int main
#define mainbody () { return 0; }
mainbody

Must be some gcc extension. This compiles not even with LCC-WIN32:

lc -ansic -O -c main.c
Error main.c: 4 Syntax error; missing semicolon before `mainbody'
Warning main.c: 4 no type specified. Defaulting to int
Error main.c: 5 Syntax error; missing semicolon before `end of input'
2 errors, 1 warning
1 error
That does tend to indicate some failings in lcc-win32.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Jun 28 '08 #20

P: n/a
Erik Trulsson <er******@student.uu.sewrites:
[...]
(It makes a great deal of difference if there is a space or not between the
macro name and a '(' when defining a macro.)
[...]

Right. But it *doesn't* matter whether there's a space between the
macro name and a '(' when *invoking* a macro.

Terminology: an "object-like macro" is one that takes no arguments; a
"function-like macro" is one that does take arguments.

For example:

#define OBJ () /* an object-like macro expanding to () */
#define FUNC() /* a function-like macro expanding to nothing */

FUNC /* Not replaced */
FUNC() /* Replaced by nothing */
FUNC () /* Also replaced by nothing; the space is irrelevant */

This isn't relevant to the example we're discussing, but I have
seen it trip up some people.

In most C syntax, whitespace is irrelevant (except as part of a
literal or to separate two tokens that otherwise might be a single
token). An exception is made in macro definitions; this special
case allows the expansion of an object-like macro to start with
'(', while allowing for function-like macros. There's no need
for such an exception for invocations of function-like macros.
If there were, it would defeat the purpose of making function-like
macros act (more or less) like function calls.

(And let me remind everyone to compile your code before posting it.
I made a really embarrassing mistake in the initial version of
the above example; I wouldn't have caught it if I hadn't tried it
out first. No, I'm not going to tell you what the mistake was.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 28 '08 #21

P: n/a
On Sat, 28 Jun 2008 00:25:39 UTC, Richard Heathfield
<rj*@see.sig.invalidwrote:
Keith Thompson said:

<snip>
There's a fairly subtle argument that "int main()" is not actually
required to be supported,

I remember that this has come up before. I wasn't completely convinced
then, and I'm not completely convinced now.

A function definition that has no parameter list takes no parameters, and
is thus precisely equivalent to int main(void) in semantic terms. (Note
that we're not talking about mere definitions here.)

Since the Standard only requires of main that it be equivalent to int
main(void) or int main(int argc, char **argv), and since int main() is
equivalent to int main(void), it seems to me that int main() is perfectly
acceptable - to the compiler, at least, even though the stylist might
object.
No, its not equivalent.

int main(void) ia a function returning int and receiving no
parameters.

Whereas int main() is a function returning int an receiving an unknown
number of parameters of unknown types.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
Jun 28 '08 #22

P: n/a
Keith Thompson wrote:
>
.... snip ...
>
Right. But it *doesn't* matter whether there's a space between
the macro name and a '(' when *invoking* a macro.

Terminology: an "object-like macro" is one that takes no
arguments; a "function-like macro" is one that does take arguments.

For example:

#define OBJ () /* an object-like macro expanding to () */
#define FUNC() /* a function-like macro expanding to nothing */

FUNC /* Not replaced */
FUNC() /* Replaced by nothing */
FUNC () /* Also replaced by nothing; the space is irrelevant */

This isn't relevant to the example we're discussing, but I have
seen it trip up some people.
Where do you see this in the standard? I always considered it as
separated by the lexer, which can find the "FUNC(" in the stream,
and expand it. However the stream "FUNC (" is textually
different. If I am full of it I want to find out.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Jun 29 '08 #23

P: n/a
Herbert Rosenau said:

<snip>
int main(void) ia a function returning int and receiving no
parameters.
Right.
Whereas int main() is a function returning int an receiving an unknown
number of parameters of unknown types.
Wrong for a definition of int main(), for reasons that I have posted
elsethread.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 29 '08 #24

P: n/a
On Sat, 28 Jun 2008 21:17:59 -0400, CBFalconer wrote:
Keith Thompson wrote:
>[...]
#define FUNC() /* a function-like macro expanding to nothing */
[...]
FUNC () /* Also replaced by nothing; the space is irrelevant */

Where do you see this in the standard? I always considered it as
separated by the lexer, which can find the "FUNC(" in the stream, and
expand it. However the stream "FUNC (" is textually different. If I am
full of it I want to find out.
6.10.3p10:
"[...] Each subsequent instance of the function-like macro name followed
by a ( as the next preprocessing token introduces the sequence of
preprocessing tokens that is replaced by the replacement list in the
definition (an invocation of the macro). [...]"

5.1.1.2p1[3]:
"3. The source file is decomposed into preprocessing tokens and sequences
of white-space characters (including comments). [...]"

Whitespace is retained by the lexer, but not as pp tokens. In FUNC (), the
next pp token after FUNC is (.
Jun 29 '08 #25

P: n/a
Erik Trulsson wrote:
) You are wrong. 'main' is defined as a function-like macro taking no arguments
) and expanding to an empty string. The 'main' in "int main" does not match an
) invocation of this macro and is thus not replaced.
) 'mainbody' on the other hand is an object-like macro which is defined as "()
) { return 0; }".

Oh right, I overlooked the parens after the mainbody macro.
My bad.
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
Jun 29 '08 #26

P: n/a
On Sun, 29 Jun 2008 03:50:36 UTC, Richard Heathfield
<rj*@see.sig.invalidwrote:
Herbert Rosenau said:

<snip>
int main(void) ia a function returning int and receiving no
parameters.

Right.
Whereas int main() is a function returning int an receiving an unknown
number of parameters of unknown types.

Wrong for a definition of int main(), for reasons that I have posted
elsethread.
You need a prototype to specifiy the type(s) and number of parameters.
Without a prototype you can't do so.

int main() is noways a prototype because it does not specifiy a bit of
type or number of parameters. Yes, it is legal C, but gives no
information about the parameters.

int main(void) as declaration is a prototype. As definition without
preceeding declaration it works as declaration too.

There is no difference between anay function and main(). Either you
defines a prototype (implicity by definition) or you does not. Without
a prototype the compiler will not able to gather the number of
parameters and theyr type. Saying in a prototype the number of
parameters is void is clearly different from having number and type of
parameters is unknown. Without prototype but with declaration you can
call a function differently in a translation unit, with a prototype
you can't. This is why prototypes are introduced in the standard.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
Jun 29 '08 #27

P: n/a
Harald van D?k wrote:
CBFalconer wrote:
>Keith Thompson wrote:
>>[...]
#define FUNC() /* a function-like macro expanding to nothing */
[...]
FUNC () /* Also replaced by nothing; the space is irrelevant */

Where do you see this in the standard? I always considered it as
separated by the lexer, which can find the "FUNC(" in the stream,
and expand it. However the stream "FUNC (" is textually different.
If I am full of it I want to find out.

6.10.3p10:
"[...] Each subsequent instance of the function-like macro name
followed by a ( as the next preprocessing token introduces the
sequence of preprocessing tokens that is replaced by the
replacement list in the definition (an invocation of the macro).
[...]"

5.1.1.2p1[3]:
"3. The source file is decomposed into preprocessing tokens and
sequences of white-space characters (including comments). [...]"

Whitespace is retained by the lexer, but not as pp tokens. In
FUNC (), the next pp token after FUNC is (.
I guess I am full of it. My technique is easier to parse, but may
not fit into doing it with lex and yacc. Time to forget that
mistake.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

Jun 29 '08 #28

P: n/a
On Sun, 29 Jun 2008 10:07:19 +0000, Herbert Rosenau wrote:
On Sun, 29 Jun 2008 03:50:36 UTC, Richard Heathfield
<rj*@see.sig.invalidwrote:
>Herbert Rosenau said:
Whereas int main() is a function returning int an receiving an
unknown number of parameters of unknown types.

Wrong for a definition of int main(), for reasons that I have posted
elsethread.
You need a prototype to specifiy the type(s) and number of parameters.
Without a prototype you can't do so.
Do you believe this code:

int main() {
static int dummy = 0;
if (dummy < 42)
{
dummy++;
return main(0, 1, 2, 3, 4, 5);
}
return 0;
}

is valid? I'm _not_ asking if you expect compilers to complain about the
code, I'm asking if you believe this code is guaranteed to behave the same
way on all current and future C implementations.
Jun 29 '08 #29

P: n/a
Herbert Rosenau said:
On Sun, 29 Jun 2008 03:50:36 UTC, Richard Heathfield
<rj*@see.sig.invalidwrote:
>Herbert Rosenau said:

<snip>
int main(void) ia a function returning int and receiving no
parameters.

Right.
Whereas int main() is a function returning int an receiving an unknown
number of parameters of unknown types.

Wrong for a definition of int main(), for reasons that I have posted
elsethread.
You need a prototype to specifiy the type(s) and number of parameters.
Without a prototype you can't do so.
Yes, you can. The Standard makes this clear, in sections that I have
already quoted in this very thread.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 29 '08 #30

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
Keith Thompson said:
<snip>
Yes, the empty list specifies, for purposes of the definition (the
body of the function), that the function has no parameters. So the
two definitions are equivalent in what they say about main's
parameters.

But they are not equivalent in other ways.

An empty list doesn't specify that a caller must pass no arguments,
because it doesn't provide a prototype.

Given "int main(void) { ... }", an attempt to call "main(42)" violates
a constraint. Given "int main(void) { ... }", such a call does not
violate a constraint (though it does invoke undefined behavior).

A prototype is not equivalent to the absence of a prototype.

Thank you. I don't think this loophole in the Standard was
intentional, but it certainly does seem to be present. At
least, I can't see any wiggle-room that might invalidate
your argument.
I remember a statement from a committee member (either on Usenet or in
a DR) that it's not worth the effort to clear up issues involving
non-prototyped functions, which are deprecated anyway.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 29 '08 #31

P: n/a
Keith Thompson wrote:
Given "int main(void) { ... }", an attempt to call "main(42)" violates
a constraint. Given "int main(void) { ... }", such a call does not
violate a constraint (though it does invoke undefined behavior).
Your second quoted example surely was meant to be "int main() { ... }";

Ralf the pedant
Jun 30 '08 #32

P: n/a
Ralf Damaschke <rw****@gmx.dewrites:
Keith Thompson wrote:
Given "int main(void) { ... }", an attempt to call "main(42)" violates
a constraint. Given "int main(void) { ... }", such a call does not
violate a constraint (though it does invoke undefined behavior).

Your second quoted example surely was meant to be "int main() { ... }";
Yes, thanks.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 30 '08 #33

P: n/a
Max
Keith Thompson wrote:
pete <pf*****@mindspring.comwrites:
>Max wrote:
This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?

Yes. Yes.
#define main()
int main
#define mainbody () { return 0; }
mainbody

It's as legal as

int main(){return 0;}

is.
[snips]
Compiling the code and/or examining the preprocessor output (assuming
your compiler supports this) won't definitively answer the question,
but it will give some good hints.
This question seems to be deeper than I thought. With '--traditional-cpp',
gcc's preprocessor produces

int main
#define mainbody () { return 0; }

mainbody

, that is, the '#define mainbody...' line is copied verbatim, without
printing any diagnostics, but only if main is a function-like macro.

Is there some older preprocessor standard that can explain that?

(Since somebody mentioned lcc-win, lcc (the original one, as well as
lcc-win and PellesC) do exactly the same.)

Jul 1 '08 #34

P: n/a
On 2008-06-27, Max <in*****@invalid.invalidwrote:
This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?

#define main()
int main
#define mainbody () { return 0; }
mainbody
If in a #define directive there is whitespace between the preprocessor symbol
and a left parenthesis which follows it, then it defines an object-like macro.
The parenthesis is part of the replacement token sequence for that macro.

Only if there is no whitespace is a function-like macro defined; the opening
parnethesis then delimits the start of the argument list.

There is no difference in C90 and C99 preprocessing in this regard.

Thus the line

int main

is not subject to any macro expansion. A function-like macro main has been
defined, which can only be invoked if its name occurs followed by an opening
parenthesis (with or without intervening whitespace).

The

#define mainbody

line defines an object-like macro mainbody whose replacement sequence consists
of the tokens ( ) { return 0 ; }.

So the line

mainbody

is subject to replacement by the token sequence.

The net effect is the program:

int main
( ) { return 0; }

This is legal C90 and C99. C99 still allows old-style function declarators;
what is gone in C99 is support for implicit int.
** Posted from http://www.teranews.com **
Jul 1 '08 #35

P: n/a
On 2008-07-01, Kaz Kylheku <kk******@gmail.comwrote:
On 2008-06-27, Max <in*****@invalid.invalidwrote:
>This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?

#define main()
int main
#define mainbody () { return 0; }
mainbody

If in a #define directive there is whitespace between the preprocessor symbol
and a left parenthesis which follows it, then it defines an object-like macro.
The parenthesis is part of the replacement token sequence for that macro.

Only if there is no whitespace is a function-like macro defined; the opening
parnethesis then delimits the start of the argument list.

There is no difference in C90 and C99 preprocessing in this regard.

Thus the line

int main

is not subject to any macro expansion.
There is some subtlety that needs to be explained.

There is a function-like macro main defined which expands to nothing.

After mainbody is expanded, it would seem that there is a call to the main
macro, since the tokens that result are:

int main () { return 0; }

However, at this stage, translation phase 4 (in C99 numbering) is already done.
No more macro expansion takes place.

Translation phase 4 makes it clear that preprocessing directives are executed
and macros are expanded, but the preproessing are deleted afterward. During the
macro expansion, the #define mainbody ... directive is not yet deleted, and so
at no point is there a main token followed by a ( token which could be
interpreted as a call to the function-like macro.

But what if it was:

#define main()
#define mainbody () { return 0; }
int main
mainbody

instead? For main to be treated as a macro, macro processing would have to work
in multiple passes, whereby the entire translation unit is repeatedly rescanned
for possible macro expansions. In the first pass, main would not be recogized
as a macro, but mainbody would be expanded to the token sequence () { return
0; }. Then on the second scan, main () would be recognized as a macro call and
expanded. I can't find any requirement for such repeated scanning for macro
expansions; it must occur once, top to bottom. Once a macro call is fully
expanded and substituted, further macro expansion takes place among the tokens
which follow. And once some identifier is skipped because it is not a macro, it
cannot be later revisited, because some macro-expanded text might make it
suddenly look like a macro.
** Posted from http://www.teranews.com **
Jul 1 '08 #36

P: n/a
Max <in*****@invalid.invalidwrites:
Keith Thompson wrote:
pete <pf*****@mindspring.comwrites:
Max wrote:
This was asked in a C test. Is the following code legal C?
Is it legal in C90? C99?

Yes. Yes.

#define main()
int main
#define mainbody () { return 0; }
mainbody

It's as legal as

int main(){return 0;}

is.

[snips]
Compiling the code and/or examining the preprocessor output (assuming
your compiler supports this) won't definitively answer the question,
but it will give some good hints.

This question seems to be deeper than I thought. With '--traditional-cpp',
gcc's preprocessor produces

int main
#define mainbody () { return 0; }

mainbody

, that is, the '#define mainbody...' line is copied verbatim, without
printing any diagnostics, but only if main is a function-like macro.

Is there some older preprocessor standard that can explain that?

(Since somebody mentioned lcc-win, lcc (the original one, as well as
lcc-win and PellesC) do exactly the same.)
There was no actual *standard* prior to the introduction of ANSI C in
1989. But there were some behaviors that were fairly common in
pre-standard preprocessors, and that were changed in the standard.

The following is somewhat off-topic in that it's specific to gcc,
particularly to the GNU preprocessor. But it's also topical in that
it applies to the behavior of pre-ANSI compilers (to the extent that
"gcc -traditional-cpp" reproduces that behavior).

The issue in this particular case seems to be that the GNU
preprocessor in traditional mode doesn't like the reference to "main"
without parentheses after "main" has been defined as a function-like
macro. In standard C. this isn't a problem; the macro definition
simply doesn't apply unless "main" is followed by a '('.

Compiling the original program:

#define main()
int main
#define mainbody () { return 0; }
mainbody

with "gcc -Wtraditional" gives:

c.c:2:5: warning: function-like macro "main" must be used with
arguments in traditional C

Apparently the preprocessor, in traditional mode, stops working once
it encountters this error, and just passes its input to its output
with no changes. After changing the first line to "#define Main()",
"gcc -E -traditional-cpp" gives:

[# directives omitted]
int main

() { return 0; }

<OT>
"info cpp Traditional" should give you information on the
preprocessor's traditional mode, and how it differs from standard
mode.
</OT>

Note that the traditional mode is inexact, and doesn't necessarily
match any particular pre-standard implementation. It's not likely to
be useful unless you have a need to handle *really* old code.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 1 '08 #37

This discussion thread is closed

Replies have been disabled for this discussion.