GCC is re-implementing in C++ and C discarded

V

Vincenzo Mercuri

Citation, please?

When the Standard says (N1570 5.1.2.2.1p1):

(...) It shall be defined with a return type of int and with no
parameters:
int main(void) { /* ... */ }
or with two parameters (referred to here as argc and argv, though
any names may be used, as they are local to the function in which
they are declared):
int main(int argc, char *argv[]) { /* ... */ }
or equivalent;10) or in some other implementation-defined manner.

footnote 10):
Thus, int can be replaced by a typedef name defined as int,
or the type of argv can be written as char ** argv, and so on.

Given that I don't think that "int main(void)" and "int main()" are
"equivalent", my claim that "it is implementation-defined whether it is
supported or not" is taken into account by the phrase "or in some other
implementation-defined manner".

The standard describes two ways of defining main(), and requires every
conforming implementation of C to support any definition of main
equivalent to one of those two ways. This form is not the same as either
one of those, but it is equivalent to the first of those two ways.
[..]

That's the point. If you say that "int main(void)" is equivalent to
"int main()" then you are saying that it is also equivalent to
"int main(int argc, char **argv, char **env)" or "int main(int argc)",
but I'm not convinced that compilers are obliged to support all these
definitions.
 
J

Jens Gustedt

Am 27.08.2012 21:48, schrieb Vincenzo Mercuri:
That's the point. If you say that "int main(void)" is equivalent to
"int main()" then you are saying that it is also equivalent to
"int main(int argc, char **argv, char **env)" or "int main(int argc)",
but I'm not convinced that compilers are obliged to support all these
definitions.

No "int main()" is equivalent to "int main(void)" for
definitions. There is this extra rule for definitions (versus just
declarations) such that these two are equivalent.

Jens
 
V

Vincenzo Mercuri

Am 27.08.2012 21:48, schrieb Vincenzo Mercuri:

No "int main()" is equivalent to "int main(void)" for
definitions. There is this extra rule for definitions (versus just
declarations) such that these two are equivalent.

Thanks, then I must have missed that part, where I can find the
definition of this equivalence?
 
J

James Kuyper

On 08/27/2012 03:56 PM, Vincenzo Mercuri wrote:
....
Thanks, then I must have missed that part, where I can find the
definition of this equivalence?

6.7.6.3p10: "The special case of an unnamed parameter of type void as
the only item in the list specifies that the function has no parameters."

6.7.6.3p14: "An empty list in a function declarator that is part of a
definition of that function specifies that the function has no parameters."

It doesn't directly say that the declarations are equivalent, but what
it says about what those declaration specify, is word-for-word identical
in both cases.
 
V

Vincenzo Mercuri

Il 27/08/2012 22:09, James Kuyper ha scritto:
On 08/27/2012 03:56 PM, Vincenzo Mercuri wrote:
...

6.7.6.3p10: "The special case of an unnamed parameter of type void as
the only item in the list specifies that the function has no parameters."

6.7.6.3p14: "An empty list in a function declarator that is part of a
definition of that function specifies that the function has no parameters."

It doesn't directly say that the declarations are equivalent, but what
it says about what those declaration specify, is word-for-word identical
in both cases.

Thank you ;)
 
K

Keith Thompson

James Kuyper said:
lovecreatesbeauty <[email protected]> writes:
[...]
I saw some C++ code like :)

void main()
{
/*...*/
}
[snip]

I don't see any relevant differences between the two languages in this
regard. Could you explain more fully how this constitutes an example of
incompatibility between C and C++?

C++, unlike C, requires main to return int, even for
implementation-defined definitions.
 
K

Keith Thompson

Jens Gustedt said:
Am 27.08.2012 21:48, schrieb Vincenzo Mercuri:

No "int main()" is equivalent to "int main(void)" for
definitions. There is this extra rule for definitions (versus just
declarations) such that these two are equivalent.

Definitions also provide declarations.

This program contains a constraint violation:

int main(void) {
if (0) main(42);
return 0;
}

This one, I argue, is strictly conforming (its behavior would be
undefined if the call were executed).

int main() {
if (0) main(42);
return 0;
}

Thus the two definitions are not equivalent, unless you use a rather
loose definition of the word "equivalent".

On the other hand, I believe it was *intended* for `int main()` to be
valid; requiring the `void` keyword would have broken existing pre-ANSI
code.

But `int main(void)` (if you don't need argc and argv) is better for
newly written C programs.
 
K

Keith Thompson

Kenneth Brody said:
On 8/24/2012 7:12 PM, Steven G. Kargl wrote: [...]
The name of the language is "Fortran". It's been Fortran since
the Fortran 1990 standard.

Noted. Note, too, that the last time I programmed in it, it was spelled
"FORTRAN". :)

<http://en.wikipedia.org/wiki/Fortran> shows the cover of a Programmer's
Reference Manual with the name "Fortran". It was published in 1956.

But there's more to it than that; see
<http://en.wikipedia.org/wiki/Fortran#Capitalization>.

[...]

Shall we get back to C now?
 
J

Jens Gustedt

Am 28.08.2012 00:20, schrieb Keith Thompson:
Definitions also provide declarations.

Yes. But the declaration that is given through the definition does not
necessarily follow the same rules as one provided by a
declaration-only.

As James has already cited upthread

6.7.6.3p14: "An empty list in a function declarator that is part of a
definition of that function specifies that the function has no parameters."
This program contains a constraint violation:

int main(void) {
if (0) main(42);
return 0;
}

This one, I argue, is strictly conforming (its behavior would be
undefined if the call were executed).

int main() {
if (0) main(42);
return 0;
}

so this function is specified as not receiving any parameters, just as
the one with void. The definition in the standard for function
prototype is

A *function prototype* is a declaration of a function that declares
the types of its parameters.

(ARAIK there is no syntax specification for prototypes.)

So this is a prototype: as you said it is a declaration, and it
specifies the types of its parameters, here in particular that there
are none. So really this is equivalent to the "(void)"
definition/declaration.
On the other hand, I believe it was *intended* for `int main()` to be
valid; requiring the `void` keyword would have broken existing pre-ANSI
code.

It is intended to be valid and it is valid.
But `int main(void)` (if you don't need argc and argv) is better for
newly written C programs.

agreed

Jens
 
A

ais523

Keith said:
This one, I argue, is strictly conforming (its behavior would be
undefined if the call were executed).

int main() {
if (0) main(42);
return 0;
}

Which language is this? There's some doubt about whether "int main()" is
valid in a hosted C implementation (although it seems to work well in
practice), and although it's legal in C++, the recursive call to main is
illegal in C++, so the program still doesn't conform properly.
 
K

Keith Thompson

Jens Gustedt said:
Am 28.08.2012 00:20, schrieb Keith Thompson: [...]
This program contains a constraint violation:

int main(void) {
if (0) main(42);
return 0;
}

This one, I argue, is strictly conforming (its behavior would be
undefined if the call were executed).

int main() {
if (0) main(42);
return 0;
}

so this function is specified as not receiving any parameters, just as
the one with void. The definition in the standard for function
prototype is

A *function prototype* is a declaration of a function that declares
the types of its parameters.

(ARAIK there is no syntax specification for prototypes.)

Does a definition with empty parenthese provide a declaration
that causes a call with parameters to be a constraint violation?
Does the second program require a diagnostic on the `main(42)` call?

Of the several compilers I've tried, only one complains about the
call, and it issues the same warning when the call is correct:
`main()` rather than `main(42)`. In all cases, I used command-line
options intended to enforce standard compliance. That doesn't prove
anything except that a number of C compiler implementers disagree
with your interpretation, at least implicitly. Did they all get
it wrong?

The compilers I tried were gcc, Solaris cc, lcc-win, and clang.
lcc-win warned "Missing prototype for 'main'" on the call --
regardless of whether the call includes an argument.
So this is a prototype: as you said it is a declaration, and it
specifies the types of its parameters, here in particular that there
are none. So really this is equivalent to the "(void)"
definition/declaration.

Consider this:

void foo() { }

void bar(n) int n; { }

The definition of `foo` specifies that it has no parameters.
The definition of `bar` specifies that it has one parameter of
type int. I believe that neither definition provides a prototype or
requires a diagnostic for a call with the wrong number of arguments.

At the very least, the current wording in the standard *can
reasonably be interpreted* so that `int main() { }` and `int
main(void) { }` are not equivalent. I'd like to see this clarified
by the committee. I've specifically proposed, in comp.std.c, adding
an explicit statement that `int main() { }` is valid -- though I'd
actually prefer removing function declarations and definitions with
empty parentheses from the language altogether, after they've been
"obsolescent" since 1989. (Existing code without prototypes can
be handled by older compilers, or by non-conforming options in
newer compilers.)

And if `void foo() { }` does provide a prototype, then *that*
needs to be made clearer; there are a lot of compilers that fail
to warn about calls like `foo(42)`.

[...]
 
K

Keith Thompson

ais523 said:
Which language is this? There's some doubt about whether "int main()" is
valid in a hosted C implementation (although it seems to work well in
practice), and although it's legal in C++, the recursive call to main is
illegal in C++, so the program still doesn't conform properly.

It's C, of course; I rarely post C++ code in comp.lang.c.
Recursive calls to main() are legal in C.

What do you mean by "valid"? If you mean that it's a constraint
violation, requiring a diagnostic, I disagree, and I'll ask you
to cite the standard to support your claim. If you mean that the
behavior is undefined, that's the point we're debating.

Though now that you mention it, I've stated my position incorrectly.
I've argued that just defining `int main() { ... }` has undefined
behavior, since it's not equivalent to `int main(void) { ... }`;
in that case, the above program is obviously not strictly conforming.

Let me restate my position more consistently.

I think we can all agree that this program is strictly conforming:

int main(void) { } /* program 1 */

Let us assume for the sake of argument that this program:

int main() { } /* program 2 */

is strictly conforming, because the two forms (`()` vs. `(void)`) are
"equivalent" as required by N1570 5.1.2.2.1p1.

I think we can agree that this program:

int main(void) { /* program 3 */
if (0) main(42);
}

violates a constraint, due to the call `main(42)`. But then this
program:

int main() { /* program 4 */
if (0) main(42);
}

would also violate a constraint, given that `int main(){}` and
`int main(void){}` are equivalent definitions.

My argument is that `int main(){}` and `int main(void){}` are *not*
equivalent definitions, since the latter provides a prototype and
the former does not. And therefore any program that defines `main`
as `int main()` has undefined behavior according to the current
wording (but perhaps not the intent) of the C standard -- unless the
implementation explicitly documents that it permits `int main(){}`,
as provided by the phrase "or in some other implementation-defined
manner" at the end of 5.1.1.2.2.1p1.

Even if the behavior is undefined, a compiler is free to accept
`int main() { }` without complaint, and every compiler I've tried
does so.

Removing `main` from the debate for a moment, clearly the following
function definition is valid:

void foo() { }

But does this function definition:

void foo() {
if (0) foo(42);
}

require a diagnostic?
 
V

Vincenzo Mercuri

Il 28/08/2012 02:34, Keith Thompson ha scritto:
[..]
Removing `main` from the debate for a moment, clearly the following
function definition is valid:

void foo() { }

But does this function definition:

void foo() {
if (0) foo(42);
}

require a diagnostic?

I agree with what you said. I believe that there is no way to answer to
this question, unless the Standard explicitly says that, in such cases,
"void foo() { }" also provides a prototype for `foo()'.
 
L

lovecreatesbeauty

6.7.6.3p10: "The special case of an unnamed parameter of type void as
the only item in the list specifies that the function has no parameters."

6.7.6.3p14: "An empty list in a function declarator that is part of a
definition of that function specifies that the function has no parameters."

It doesn't directly say that the declarations are equivalent, but what
it says about what those declaration specify, is word-for-word identical
in both cases.

Thank you.

the n1570.pdf has both presented.

int main(){} /* 1 */
int main(void){} /* 2 */

"C: A Reference Manual, 5th" states

form 1 "also OK, but not recommended" in sec 9.9, and in sec 9.2
"void is optional in function definition but needed in prototype".
 
K

Keith Thompson

lovecreatesbeauty said:
Thank you.

the n1570.pdf has both presented.

int main(){} /* 1 */
int main(void){} /* 2 */

What? No, N1570 never mentions `int main(){}`. It presents two
definitions of main that must be supported by all hosted
implementations:

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

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

"or equivalent; or in some other implementation-defined manner."
(C99 and C90 are essentially the same.)

[...]
 
A

ais523

Keith said:
It's C, of course; I rarely post C++ code in comp.lang.c.
Recursive calls to main() are legal in C.
Right; in a thread that is discussing both C and C++ (and has had many
examples of both to compare), it's less clear.
What do you mean by "valid"? If you mean that it's a constraint
violation, requiring a diagnostic, I disagree, and I'll ask you
to cite the standard to support your claim. If you mean that the
behavior is undefined, that's the point we're debating.
I think I was thinking about strict conformance, more than anything
else. And I missed that 5.1.2.2.1 is placing a requirement on
definitions, not on declarations.

[snip]
My argument is that `int main(){}` and `int main(void){}` are *not*
equivalent definitions, since the latter provides a prototype and
the former does not. And therefore any program that defines `main`
as `int main()` has undefined behavior according to the current
wording (but perhaps not the intent) of the C standard -- unless the
implementation explicitly documents that it permits `int main(){}`,
as provided by the phrase "or in some other implementation-defined
manner" at the end of 5.1.1.2.2.1p1.
I've sort-of changed my mind on this when writing this post. 5.1.2.2.1p1
is placing requirements on the definition of main. 5.1.2.2.1p2 is
putting separate requirements on the declaration. If you write `int
main() { }`, that's both a definition and a declaration; the definition
seems to be equivalent to the definition with an explicit `void`, and
the declaration is clearly different, due to the lack of a prototype.

So the question boils down to whether a prototype is part of a
definition. It clearly matters sometimes, because if there's no
prototype, integers smaller than ints get widened to ints (and then
narrowed again, if declared narrower and you aren't in a varargs
function): 6.5.2.2p6. (And prototypeless functions are still around even
in C11.)
 
E

eq mail

What?  No, N1570 never mentions `int main(){}`.

Yes it does, at least twice (see examples on pages 91 and 135).
It presents two definitions of main that must be supported
by all hosted implementations:

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

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

"or equivalent; or in some other implementation-defined manner."
(C99 and C90 are essentially the same.)

Although it lists the former as an example of the first possible
scenario, I think more important is the actual description, which
reads:

It [main] shall be defined with a return type of int and with
no parameters.

Which the following *will* do (while possibly failing to provide a
prototype for itself):

int main() { }
 
K

Keith Thompson

eq mail said:
Yes it does, at least twice (see examples on pages 91 and 135).

The example on page 91 is in section 6.5.3.4 paragraph 8. The example
on page 135 is in section 6.7.6.3 paragraph 20. Every PDF reader I've
used makes it *much* easier to find things by section number than by
page number (all the page numbers in N1570 are off by 18).

But yes, you're right, N1570 does mention `int main()` (but never
in normative text). Either I didn't know that or I had forgotten it.
Thanks for pointing it out.
It presents two definitions of main that must be supported
by all hosted implementations:

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

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

"or equivalent; or in some other implementation-defined manner."
(C99 and C90 are essentially the same.)

Although it lists the former as an example of the first possible
scenario, I think more important is the actual description, which
reads:

It [main] shall be defined with a return type of int and with
no parameters.

I don't think that either the description or the code is, or should be,
more important than the other. They're both normative and they should
be consistent. The two definitions of `main` could easily have been
marked as examples; they aren't.

The description of the two-parameter form:

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):

is incomplete, since it says nothing about the types of those two
parameters; we need the actual code:

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

to know that they're of type `int` and `char**`.

Similarly, I'd say that the description of the zero parameter form:

... and with no parameters:

is incomplete, and requires the code:

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

to specify just *how* it's defined with no parameters.
Which the following *will* do (while possibly failing to provide a
prototype for itself):

int main() { }

You can safely define main in a way that's "equivalent" to one of
the two forms given, both of which are presented by a combination
of English text and C code. Variations such as using a typedef for
int rather than int, or using different names for argc and argv,
or writing `char **argv` rather than `char *argv[]`, clearly provide
equivalent definitions. It's far less clear that `int main() { }`
does so.

The examples you cite do strongly imply that `int main(){}` was
*intended* to be a valid definition, as does the observation that
making it invalid would have broken pre-ANSI code, something the
C89 committee was generally careful to avoid. My argument is that
the wording of the standard does not accurately reflect this intent.

I'ts plausible that the committee meant for us to assume that `int
main(void){}` and `int main(){}` are "equivalent". They certainly are
equivalent *in some ways*. My reading is that they are *not* entirely
equivalent, and their partial equivalence is not enough to say that
they're "equivalent". This at least needs to be made clearer.

(Dropping old-style function declarations and definitions, as the
standard has been threatening to do since 1989, would neatly resolve
this.)
 
J

James Kuyper

Definitions also provide declarations.

This program contains a constraint violation:

int main(void) {
if (0) main(42);
return 0;
}

This one, I argue, is strictly conforming (its behavior would be
undefined if the call were executed).

int main() {
if (0) main(42);
return 0;
}

Thus the two definitions are not equivalent, unless you use a rather
loose definition of the word "equivalent".

On the other hand, I believe it was *intended* for `int main()` to be
valid; requiring the `void` keyword would have broken existing pre-ANSI
code.

But `int main(void)` (if you don't need argc and argv) is better for
newly written C programs.

I knew of your arguments for this interpretation, and I'm not sure that
you're wrong (though I wish you were). However, the original context of
this subthread was an assertion that this issue constituted an
incompatibility between C and C++. The issue doesn't come up in C++, and
while your arguments seem reasonable, I don't believe that many (any?)
actual implementations of C treat this code in a way incompatible with
the way C++ treats it. While it might, in theory, be a potential
incompatibility, it is not a real one.
 
J

James Kuyper

James Kuyper said:
)

void main()
{
/*...*/
}
[snip]

I don't see any relevant differences between the two languages in this
regard. Could you explain more fully how this constitutes an example of
incompatibility between C and C++?

C++, unlike C, requires main to return int, even for
implementation-defined definitions.

True. That doesn't strike me as a good example of a C/C++
incompatibility, since relying upon implementation-defined alternative
definitions of main is sufficient to allow incompatibility even between
two different compilers for the same language.
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
474,077
Messages
2,570,569
Members
47,206
Latest member
MalorieSte

Latest Threads

Top