Hello,
I read section 6.7.5.3p14 from C99 several times but it looks I missed
something in my understanding...
I put the revelant section for convenience:
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 to check that I understood correctly this, I wrote and tried to
compile the following code:
--- 8< ---
/*
* A function declaration with empty identifier list which is part of
* the definition specifies that the function has no parameters.
*/
int foo()
{
return 1;
}
/* A function declaration alone with empty list identifier specifies
* that no information about the number or types of the parameters is
* supplied.
*/
int bar();
void test(void)
{
foo(1); /* should fail */
bar(1); /* should be ok */
}
--- >8 ---
Gcc compiles this without any warnings (gcc -Wall -std=c99 -c func.c).
However I would expect gcc to issue an error or a warning since 'foo'
function takes no parameters (in my understanding).
Could anybody enlight me ?
Thanks
|
|
0
|
|
|
|
Reply
|
Francis
|
11/26/2009 1:29:03 PM |
|
Francis Moreau wrote:
> Hello,
>
> I read section 6.7.5.3p14 from C99 several times but it looks I missed
> something in my understanding...
>
> I put the revelant section for convenience:
>
> 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 to check that I understood correctly this, I wrote and tried to
> compile the following code:
>
> --- 8< ---
>
> /*
> * A function declaration with empty identifier list which is part of
> * the definition specifies that the function has no parameters.
> */
> int foo()
> {
> return 1;
> }
>
> /* A function declaration alone with empty list identifier specifies
> * that no information about the number or types of the parameters is
> * supplied.
> */
> int bar();
>
> void test(void)
> {
> foo(1); /* should fail */
> bar(1); /* should be ok */
> }
>
> --- >8 ---
>
> Gcc compiles this without any warnings (gcc -Wall -std=c99 -c func.c).
> However I would expect gcc to issue an error or a warning since 'foo'
> function takes no parameters (in my understanding).
>
> Could anybody enlight me ?
A definition is also a declaration, but the two roles are
not always in perfect lock-step. `int foo() { return 1; }'
defines a function with no parameters, but as a declaration it
gives no information about the parameters. (Almost none: we
know that foo has no "..." parameters, but that's all.)
This odd state of affairs may make just a little sense if
you think about the declaration you'd get by chopping off
foo's body and tacking on a semicolon: `int foo();'. That
declaration gives (almost) no information about foo's parameters,
just like your declaration of bar. That declaration, roughly
speaking, is the "external appearance" of foo; the additional
details are "private" to the definition itself.
Recommendation: Don't write old-style function definitions
in new code, and rewrite old-style to new-style whenever you have
a good reason to visit a module containing them. Note that it is
not always possible to write a portable prototype for an old-style
function: in `int barf(s) unsigned short s; { return s >> 3; }',
an `unsigned short' argument promotes to `int' on some platforms
and to `unsigned int' on others, so we don't know which to write
in a prototype. Do a full change-over and all will be well.
--
Eric Sosman
esosman@ieee-dot-org.invalid
|
|
0
|
|
|
|
Reply
|
Eric
|
11/26/2009 3:20:12 PM
|
|
Francis Moreau <francis.moro@gmail.com> writes:
> I read section 6.7.5.3p14 from C99 several times but it looks I missed
> something in my understanding...
>
> I put the revelant section for convenience:
>
> 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 to check that I understood correctly this, I wrote and tried to
> compile the following code:
>
> --- 8< ---
>
> /*
> * A function declaration with empty identifier list which is part of
> * the definition specifies that the function has no parameters.
> */
> int foo()
> {
> return 1;
> }
>
> /* A function declaration alone with empty list identifier specifies
> * that no information about the number or types of the parameters is
> * supplied.
> */
> int bar();
>
> void test(void)
> {
> foo(1); /* should fail */
> bar(1); /* should be ok */
> }
>
> --- >8 ---
>
> Gcc compiles this without any warnings (gcc -Wall -std=c99 -c func.c).
> However I would expect gcc to issue an error or a warning since 'foo'
> function takes no parameters (in my understanding).
That might be a good idea, but it does not have to. Calling a
function with the wrong parameter list is not a constraint violation
unless there is a prototype in scope. Add (void) to the function
definition and declaration and both will act as a prototype as well.
gcc will then warn you that they are being called incorrectly.
Add -Wstrict-prototypes and you will be told that neither the
definition of foo nor the declaration of bar acts as a prototype. I
always have this warning on since it lets me know that I have written
a function whose calls won't be checked.
--
Ben.
|
|
0
|
|
|
|
Reply
|
Ben
|
11/26/2009 3:21:50 PM
|
|
On Nov 26, 4:21=A0pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> Francis Moreau <francis.m...@gmail.com> writes:
> > Gcc compiles this without any warnings (gcc -Wall -std=3Dc99 -c func.c)=
..
> > However I would expect gcc to issue an error or a warning since 'foo'
> > function takes no parameters (in my understanding).
>
> That might be a good idea, but it does not have to. =A0Calling a
> function with the wrong parameter list is not a constraint violation
> unless there is a prototype in scope.
Ah ok, I thought it has to for definition case.
> =A0Add (void) to the function
> definition and declaration and both will act as a prototype as well.
> gcc will then warn you that they are being called incorrectly.
>
> Add -Wstrict-prototypes and you will be told that neither the
> definition of foo nor the declaration of bar acts as a prototype. =A0I
> always have this warning on since it lets me know that I have written
> a function whose calls won't be checked.
>
I'll do the same.
Thanks you
|
|
0
|
|
|
|
Reply
|
Francis
|
11/30/2009 10:54:44 AM
|
|
On Nov 26, 4:20=A0pm, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
>
> =A0 =A0 =A0A definition is also a declaration, but the two roles are
> not always in perfect lock-step. =A0`int foo() { return 1; }'
> defines a function with no parameters, but as a declaration it
> gives no information about the parameters. =A0(Almost none: we
> know that foo has no "..." parameters, but that's all.)
Well still, reading 6.7.5.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's still unclear if the function has no parameters for the
definition or as a declaration.
>
> =A0 =A0 =A0This odd state of affairs may make just a little sense if
> you think about the declaration you'd get by chopping off
> foo's body and tacking on a semicolon: `int foo();'. =A0That
> declaration gives (almost) no information about foo's parameters,
> just like your declaration of bar. =A0That declaration, roughly
> speaking, is the "external appearance" of foo; the additional
> details are "private" to the definition itself.
ok I think I got your idea, but I'm still not sure this is equivalent
to 6.7.5.3p14.
But it's a good way to remember the rule.
>
> =A0 =A0 =A0Recommendation: Don't write old-style function definitions
> in new code, and rewrite old-style to new-style whenever you have
> a good reason to visit a module containing them. =A0Note that it is
> not always possible to write a portable prototype for an old-style
> function: in `int barf(s) unsigned short s; { return s >> 3; }',
> an `unsigned short' argument promotes to `int' on some platforms
> and to `unsigned int' on others, so we don't know which to write
> in a prototype. =A0Do a full change-over and all will be well.
Indeed.
Thanks
|
|
0
|
|
|
|
Reply
|
Francis
|
11/30/2009 11:23:45 AM
|
|
Francis Moreau <francis.moro@gmail.com> writes:
> On Nov 26, 4:20 pm, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:
>>
>> A definition is also a declaration, but the two roles are
>> not always in perfect lock-step. `int foo() { return 1; }'
>> defines a function with no parameters, but as a declaration it
>> gives no information about the parameters. (Almost none: we
>> know that foo has no "..." parameters, but that's all.)
>
> Well still, reading 6.7.5.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's still unclear if the function has no parameters for the
> definition or as a declaration.
I think Eric's words are a little confusing. Let me try to be clear.
There are four things to consider:
1. int foo() { return 1; }
2. int foo();
3. int foo(void) { return 1; }
4. int foo(void);
All four act as declarations of the function but only 1 and 3 are also
definitions. 3 and 4 also provide a prototype whereas 1 and 2 do not.
2 says the least. As a declarator with an empty parameter list that
is *not* part of a definition is says nothing about foo's parameters.
1, 3 and 4 all say that foo has no parameters but calls to foo with a
parameter will only be diagnosed in the case of 3 and 4. A compiler
is permitted to complain about foo(42) after seeing 1, but to do so it
need to distinguish between 1 and 2 because foo(42) is *not* wrong
after seeing only 2. I don't know a compiler that does this. For one
thing, it would involve a lot of effort being put into old-style
definitions.
<snip>
--
Ben.
|
|
0
|
|
|
|
Reply
|
Ben
|
11/30/2009 2:11:41 PM
|
|
|
5 Replies
111 Views
(page loaded in 0.113 seconds)
|