Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > GCC is re-implementing in C++ and C discarded

Reply
Thread Tools

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

 
 
Keith Thompson
Guest
Posts: n/a
 
      08-27-2012
Jens Gustedt <(E-Mail Removed)> writes:
> 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)`.

[...]

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      08-28-2012
ais523 <(E-Mail Removed)> writes:
> Keith Thompson wrote:
>> 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.


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?

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
Vincenzo Mercuri
Guest
Posts: n/a
 
      08-28-2012
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()'.

--
Vincenzo Mercuri
 
Reply With Quote
 
lovecreatesbeauty
Guest
Posts: n/a
 
      08-28-2012
On Monday, August 27, 2012 8:09:45 PM UTC, James Kuyper 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.

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".
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      08-28-2012
lovecreatesbeauty <(E-Mail Removed)> writes:
> On Monday, August 27, 2012 8:09:45 PM UTC, James Kuyper 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.
>
> 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.)

[...]

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
ais523
Guest
Posts: n/a
 
      08-28-2012
Keith Thompson wrote:
> ais523 <(E-Mail Removed)> writes:
>> Keith Thompson wrote:
>>> 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.

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

--
ais523
 
Reply With Quote
 
eq mail
Guest
Posts: n/a
 
      08-28-2012
On Aug 28, 4:34*am, Keith Thompson <(E-Mail Removed)> wrote:
> lovecreatesbeauty <(E-Mail Removed)> writes:
> > On Monday, August 27, 2012 8:09:45 PM UTC, James Kuyper 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.

>
> > the n1570.pdf has both presented.

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

>
> 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() { }

> [...]

 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      08-28-2012
eq mail <(E-Mail Removed)> writes:
> On Aug 28, 4:34 am, Keith Thompson <(E-Mail Removed)> wrote:
>> lovecreatesbeauty <(E-Mail Removed)> writes:

[...]
>> > the n1570.pdf has both presented.

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

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

>
> 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 1.

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

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      08-28-2012
On 08/27/2012 06:20 PM, Keith Thompson wrote:
> Jens Gustedt <(E-Mail Removed)> writes:
>> 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.

>
> 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.
--
James Kuyper
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      08-28-2012
On 08/27/2012 06:08 PM, Keith Thompson wrote:
> James Kuyper <(E-Mail Removed)> writes:
>> On 08/27/2012 03:19 AM, lovecreatesbeauty wrote:
>>> On Monday, August 27, 2012 4:04:57 AM UTC, Keith Thompson wrote:
>>>> lovecreatesbeauty <(E-Mail Removed)> 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.


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.
--
James Kuyper
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: GCC is re-implementing in C++ and C discarded Nomen Nescio C Programming 0 08-26-2012 10:34 AM
Re: GCC is re-implementing in C++ and C discarded Anonymous C Programming 10 08-26-2012 08:04 AM
Cisco VPN client, packets beeing discarded and bypassed seansan Cisco 3 09-24-2006 10:50 AM
discarded iterator.next() at interactive global scope doesn't bump interator?? Bengt Richter Python 2 09-04-2005 12:17 PM
Linker Message: "discarded section" Hartmut Sbosny C++ 2 05-29-2005 12:20 AM



Advertisments