int main(void) { /* ... */ }
or
int main(int argc, char *argv[]) { /* ... */ }
or equivalent. Or in some implementation-defined manner (not strictly
conforming anymore).
Because "int main() { }" is not equivalent to "int main(void) { }", I take
it that "int main() { }" is not supported for strictly conforming programs?
I agree.
If the implementation documents that "int main()" is permitted,
then a program that uses it is well-behaved, with its behavior
defined by the implementation.
Otherwise, such a program's behavior is undefined.
In practice, the actual behavior for "int main()" is almost certain to
be the same as "int main(void)".
--
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"
Keith Thompson wrote:
> In practice, the actual behavior for "int main()" is almost certain to
> be the same as "int main(void)".
Here's a related question, since I'm not as adept at ISO C
as I once was...
Given a function definition of:
int main() { ... }
does the standard state that this is substantially different
from:
int main(void) { ... }
My point of view is that since main() receives no arguments,
including any varargs, how can it have any calling linkage
different than 'main(void)'?
They're not equivalent as declarations because one acts as a prototype and
the other doesn't, but they are equivalent as definitions (they both
define main as a function taking no arguments). I'm sure the committee
indended to allow both for strictly conforming programs, but one could
argue that the standard doesn't actually say that (and Keith Thompson
[forgive me if I've misspelled your name, Keith] probably will, if he
hasn't already).
--
Larry Jones
I've got to start listening to those quiet, nagging doubts. -- Calvin
The key here is the meaning of "substantially different". The spec requires
no diagnostic for
int main() {
main("lulz");
}
I prefer to get errors in my code if I do a mistake, so I would consider
this a substantial difference.
Can't we move this discussion to comp.std.c???
We have discussed this here a zillion times already.
Yes, and we should not cast the result of malloc. Yes I know.
BUT PLEEEEEEEZE....
Section 6.91, footnote 137, has examples which show
that two function definitions like those above,
are compatible.
typedef int F(void); // type F is 荘function with no parameters
// returning int鋳
int f(void) { /* ... */ } // RIGHT: f has type compatible with F
int g() { /* ... */ } // RIGHT: g has type compatible with F
--
pete
The key point is that the requirement specified by the standard is that
any alternatives be "equivalent" to the specified forms, not
"compatible" with them. Unlike "compatible", the standard provide no
specific definition of "equivalent" that applies in this context. The
closest it comes is footnote 9, which lists a couple of ways in which
the declaration can be different while remaining equivalent. Those
examples neither clearly include nor clearly exclude this case. The
Rationale does not address this issue either.
However, the fact that it did not use the word "compatible", even though
the word was available and well-defined, implies that "compatible" would
not have conveyed the intent of that passage.
--
James Kuyper
enum compatible_with_int_1 { please=-1, dont, let };
enum compatible_with_int_2 { this=-1, be, valid };
/* whether the enums are compatible with int is implementation-
defined. */
int check_compatibility_1;
enum compatible_with_int_1 check_compatibility_1;
int check_compatibility_2;
enum compatible_with_int_2 check_compatibility_2;
/* if they are not, a diagnostic will be generated for the above
lines.
but on my system, they are compatible. */
enum compatible_with_int_1 main(void) {
int (*p)(void) = main;
return 0;
}
This definition of main is compatible with but not equivalent to int
main(void): unlike int main(void), it is incompatible with enum
compatible_with_int_2 main(void). And unlike the int main() case,
there is no possible way to argue that this is "equivalent as a
definition only".
I'd say that 5.1.2.2.1p1 doesn't permit this *unless* the
implemetation documents it as "some other implementation-defined
manner".
If it is, then 5.1.2.2.3 applies; since the return type is compatible
with int, the status returned to the host environment is defined.
If the implementation permits "long main(void)", then 5.1.2.2.3
doesn't apply, and the status returned to the host environment is
undefined (unless the implementation defines it, which it certainly
should). (Note that int and long are not compatible even if they
happen to have the same representation.)
> On 03/11/2011 11:46 PM, pete wrote:
> > David R Tribble wrote:
<snip: is int main() 'equivalent' to int main(void) and thus legit?>
> > Section 6.91, footnote 137, has examples which show
> > that two function definitions like those above,
> > are compatible.
> >
Aside: that's 6.9.1.
> > typedef int F(void); // type F is ??function with no parameters
> > // returning int??
> >
> > int f(void) { /* ... */ } // RIGHT: f has type compatible with F
> > int g() { /* ... */ } // RIGHT: g has type compatible with F
>
True; but int g() is also compatible with int h(int x, double y).
Function compatibility is much weaker for K&R1-style function
declarations, including definitions functioning(!) as declarations.
See 6.7.5.3p16 for details, although not much explanation.
So 'compatible' can't be, and per below isn't, the criterion used.
Useless aside: pete's newsreader (which identifies as Mozilla 3) used
Microsoft's nonstandard 'smart' quotes 0x91 and 0x92 but asserted
charset=iso-8859-1, and yours (ditto Mozilla 5) properly but
unhelpfully munged to UTF-8 U+FFFD Replacement.
I can't check what's actually in the Standard here, only what Adobe
Reader gives me, and I trust that as far as I can throw it.
> The key point is that the requirement specified by the standard is that
> any alternatives be "equivalent" to the specified forms, not
> "compatible" with them. Unlike "compatible", the standard provide no
> specific definition of "equivalent" that applies in this context. The
> closest it comes is footnote 9, which lists a couple of ways in which
> the declaration can be different while remaining equivalent. Those
> examples neither clearly include nor clearly exclude this case. The
> Rationale does not address this issue either.
>
Yes the documents don't clearly say so, but J11 must have intended to
allow K&R1-style for both 0-arg and 2-arg forms. As Tim Rentsch says,
in 1999 there was still a lot of K&R1-style code, and C99 retains
K&R1-style declaration and definition even though C89 had labelled
them obsolescent (and C99 still does). Even further, C89 didn't have
the wording "or equivalent (footnote 9)" yet in 1989 ALL existing code
was K&R1, and J11's mandate, secondary only to getting a standard at
all, was to preserve existing (K&R1) code.