Re: Why is this not an error in Visual C?
- From: Eric Sosman <Eric.Sosman@xxxxxxx>
- Date: Mon, 04 May 2009 18:17:24 -0400
Kaz Kylheku wrote:
This is not a constraint, but it's a semantic rule. The rule essentially
says that when an old-style function definition is processed, then
the parameter declarations are incorporated into the type info for that
function.
Up to here, I believe you're right. The function is defined,
has a type, and the type comes from the definition.
The function is declared to have a type which includes information
about the number of parameters which it has, and their types.
... but here I think you're wrong. The definition is a declaration,
but I don't think an old-style definition declares the types (or
number) of the parameters. That is, I think, `int f(x) int x; {...}'
furnishes a declaration equivalent to `int f()', not `int f(int)'.
As far as I'm concerned, this full type info constitutes a prototype.
No reasonable, sane distinction can be drawn between the term ``prototype'' as
used in the context of the C language, and ``the state of knowing the number
and types of arguments of a function''.
Footnote 125 to 6.7.5.3p14, although of course not normative,
seems highly suggestive. Concerning the compatibility of function
types, it says "If both function types are ‘‘old style’’, parameter
types are not compared." If "the state of knowing the number and
types of arguments of a function" persisted beyond the old-style
definition, it's hard to imagine why this footnote would exist: the
type-and-number information would still be around, and there'd be
no reason not to check. A footnote pointing out that checking is not
performed thus suggests that the information does not persist.
The constraint that is violated is elsewhere, as Han From China pointed
out, namely in 6.7{4}:
All declarations in the same scope that refer to the same object or function
shall specify compatible types.
The *declared* types are compatible, since the old-style
definition declares nothing about the parameters. It turns out
that the new-style declaration describes a parameter list that
is incompatible with the old-style definition, but that's another
kettle of fish.
Given these declarations:
int foo(int);
int foo(x)
double x;
{
}
It's clear that they have incompatible types by 6.7.5.13{15} and that they are
two declarations for the same identifier, in the same scope, which consequently
violates 6.7{4}.
The first part is clear; the part after "and" is murky at best.
Now this second declaration is supposedly not a prototype. What this means is
that even though C implementations are required to record the full type
information for a function definition, even if it is old-style, they must not
use it when translating calls to the function. Doh?
Right. Try it yourself:
int f(x) int x; { return x; }
int main(void) { return f("Hello, world!"); }
For what it's worth, gcc 4.3.2 with "-W -Wall -ansi -pedantic" issues
no diagnostics for this erroneous source. The behavior of a compiler
is non-normative, but again highly suggestive.
If the compiler knows what the parameter types are, it should generate code
which converts the argument expressions to those types, and diagnose any
constraints if the expressions are not assignment-compatible compatible with
the parameter types.
Yes. Since it doesn't do so, "if the compiler knows" is false.
For instance after the definition
int foo(a)
int a;
{
}
the call
foo(3.0);
should behave exactly as if we had:
extern int foo(int);
foo(3.0);
this is because foo was in fact declared to have type ``int (int)''.
The function was defined that way, but not declared that way.
The behavior is undefined because a double is not an int, whereas
if the prototype were around the double would be converted to an
int and all would be well.
FWIW, on my implementation foo(3.0) causes `a' to take on
the value zero.
This is like not fastening a seatbelt or putting on a life jacket, when these
safety devices are available.
State-of-the-art statically typed languages go out of the way to infer type
information in the absence of declarations, yet here it is being thrown away.
Presumably because "existing code is important," as it says in
the Rationale, even if that code is not an exemplar of cleanliness.
Similar considerations probably underlay the decision to make string
literals char[] instead of const char[], and to retain gets().
--
Eric.Sosman@xxxxxxx
.
- Follow-Ups:
- Re: Why is this not an error in Visual C?
- From: Han from China
- Re: Why is this not an error in Visual C?
- References:
- Re: Why is this not an error in Visual C?
- From: Kaz Kylheku
- Re: Why is this not an error in Visual C?
- From: Han from China
- Re: Why is this not an error in Visual C?
- From: Kaz Kylheku
- Re: Why is this not an error in Visual C?
- From: Ben Bacarisse
- Re: Why is this not an error in Visual C?
- From: Kaz Kylheku
- Re: Why is this not an error in Visual C?
- Prev by Date: Re: Why is this not an error in Visual C?
- Next by Date: Re: Books
- Previous by thread: Re: Why is this not an error in Visual C?
- Next by thread: Re: Why is this not an error in Visual C?
- Index(es):
Relevant Pages
|