Strange function use

  • Thread starter Christian Christmann
  • Start date
C

Christian Christmann

Hi,

in a benchmark I've found an uncommon use of a function.
This is the simplified form:

1 int foo( int f )
2 {
3 return f;
4 }
5
6 int main( void )
7 {
8 int a, b, foo();
9 a = 10;
10 b = foo( a );
11
12 return 0;
13 }

I don't understand the use of function "foo" in line 8.
What's it's purpose? It's called without assigning it's
return value to any variable. Furthermore, I wonder
why this function use is allowed at all. According to
the function prototype "foo" expects an integer argument
that is in line 8 not given. Compiling the code with
"gcc -Wall -ansi" does not issue any warning/errors.

Could you shed some light on that.

Regards,
Chris
 
P

pemo

Christian said:
Hi,

in a benchmark I've found an uncommon use of a function.
This is the simplified form:

1 int foo( int f )
2 {
3 return f;
4 }
5
6 int main( void )
7 {
8 int a, b, foo();
9 a = 10;
10 b = foo( a );
11
12 return 0;
13 }

I don't understand the use of function "foo" in line 8.
What's it's purpose? It's called without assigning it's
return value to any variable. Furthermore, I wonder
why this function use is allowed at all. According to
the function prototype "foo" expects an integer argument
that is in line 8 not given. Compiling the code with
"gcc -Wall -ansi" does not issue any warning/errors.

Could you shed some light on that.

It's not a /call/ but a declaration - it's say that foo is a function
returning an int. I believe it's also /saying/ that foo takes an unknown
number/type of args - however, as foo's definition is in scope, the compiler
already knows about it ... thus the declaration in line 8 isn't necessary.
 
L

lovecreatesbeauty

Christian said:
1 int foo( int f )
2 {
3 return f;
4 }
5
6 int main( void )
7 {
8 int a, b, foo();

int a, b, foo( int );
9 a = 10;
10 b = foo( a );
11
12 return 0;
13 }

I don't understand the use of function "foo" in line 8.
What's it's purpose? It's called without assigning it's
return value to any variable. Furthermore, I wonder
return value to any variable. Furthermore, I wonder
why this function use is allowed at all. According to
the function prototype "foo" expects an integer argument
that is in line 8 not given. Compiling the code with
"gcc -Wall -ansi" does not issue any warning/errors.

int foo( ); /*int foo( int );*/

It's not a function use/call, foo() occurs inside a declaration. It's a
function prototype declaration.
 
L

lovecreatesbeauty

Christian said:
1 int foo( int f )
2 {
3 return f;
4 }
5
6 int main( void )
7 {
8 int a, b, foo();

int a, b, foo(); /*A*/
int a, b = foo(); /*B*/
9 a = 10;
10 b = foo( a );
11
12 return 0;
13 }

Differentiate line A and B. A function call occurs at line B.
 
C

Christian Christmann

int a, b, foo( int );


int foo( ); /*int foo( int );*/

It's not a function use/call, foo() occurs inside a declaration. It's a
function prototype declaration.

But it's a declaration that deviates from the declaration
given in line 1. There's no function "foo" defined without
any parameters, so why is the declaration from line 8
accepted by a compiler?
 
P

pemo

Christian said:
But it's a declaration that deviates from the declaration
given in line 1. There's no function "foo" defined without
any parameters, so why is the declaration from line 8
accepted by a compiler?

I think it's because you're saying that it can take any number/type of
args - and that doesn't conflict with the definition - which shows it takes
one arg of type int.

Change line 8 to, say >>> 8 int a, b, foo(float);

and then there'll be a conflict.
 
S

spibou

pemo said:
It's not a /call/ but a declaration - it's say that foo is a function
returning an int. I believe it's also /saying/ that foo takes an unknown
number/type of args - however, as foo's definition is in scope, the compiler
already knows about it ... thus the declaration in line 8 isn't necessary.

What are the semantics of declaring a function inside
another function ?
 
S

spibou

pemo said:
(e-mail address removed) wrote:

A declaration of a function is just a /prototype/ - ok?

Let me rephrase. If foo2 is declared inside foo1 are you
allowed to call foo2 only inside foo1 ? If this is so then
since you cannot define foo2 inside foo1 then you cannot
call it at all (you can call some function with the same name
but not the one you declared) which basically means that
the declaration was a waste of time. Have I got it right ?
==============
Not a pedant
==============

Hmmmmmm.

Spiros Bousbouras
 
E

Eric Sosman

pemo said:
Christian Christmann wrote:
[...]
8 int a, b, foo();
[...]
>
A declaration of a function is just a /prototype/ - ok?

No function declaration "is" a prototype, and this
declaration "has" no prototype.

The "prototype" is the description of the function's
argument list, either in a declaration or a definition (a
definition also declares). The prototype part is

int bar(double trouble);
^^^^^^^^^^^^^^

void baz(int x)
^^^^^
{
printf ("%d\n", x);
}

void xyzzy(void);
^^^^

void plugh(const char*, ...);
^^^^^^^^^^^^^^^^

An "old-style" or "K&R" declaration like `int foo();' has
no prototype. Nor does an old-style definition:

double avg(x, y)
double x, y;
{
return (x + y) * 0.5;
}

(Why is it important to keep the nomenclature straight?
Because C's declarations are a source of confusion already,
and we should not add to it by misusing the terminology. If
I feel like calling `extern int x;' a "prototype" for the
variable x, no one will stop me -- but no one will appreciate
my muddying of the waters, either. That's why I never call
`extern int x;' a "prototype," but use the term "beta." ;-)
 
C

Chris Torek

Let me rephrase. If foo2 is declared inside foo1 are you
allowed to call foo2 only inside foo1 ?

Not exactly ... but the declaration has block scope, just as
any other declaration at block scope has block scope. Consider,
e.g., the following (bad) code:

void foo1(void) {
double foo2(char *);
double x;

x = foo2("hello world");
...
}

void glork(void) {
int y;

y = foo2(42); /* something is probably wrong here */
...
}

Inside foo1(), we told the compiler "foo2() takes one argument
of type char *, and returns a value of type double".

Inside foo1(), we then call foo2(), with a call that matches the
declaration.

Later, inside glork(), we do *not* tell the compiler anything about
foo2(), and then we call it with one "int" and expect it to return
an "int".

In C99, this call requires a diagnostic, because we are calling a
function we have not declared -- the declaration vanished when it
went out of scope, at the end of foo1().

In C89, no diagnostic is required: the function is implicitly
declared as returning "int". But if foo2() really takes one
"char *" and really returns one "double", we have called it
incorrectly and used a value it never returned, so we should
probably expect things to go wrong.

If foo2() really takes one int and returns one int, we have called
it incorrectly in foo1(), and we can expect things to go wrong
there instead.

A good C89 compiler can (but does not have to) remember how foo2()
was declared inside foo1(), and point out any later conflicts, like
the one in glork(), even after the name has gone out of scope.
 
S

spibou

Eric said:
The "prototype" is the description of the function's
argument list, either in a declaration or a definition (a
definition also declares). The prototype part is

int bar(double trouble);
^^^^^^^^^^^^^^

So the return type is not part of the prototype ?
Why not ? I mean since the return type is important
for correct invocation and error checking, it would make
sense to me if it was part of the prototype.
 
E

Eric Sosman

Eric Sosman wrote:




So the return type is not part of the prototype ?
Why not ?

"Why not?" Because of 6.9.1/7:

"The declarator in a function definition specifies the
name of the function being defined and the identifiers
of its parametsrs. [Note omission of return type.] If
the declarator includes a parameter type list, [...]
such a declarator also serves as a function prototype
for later calls to the same function [...]"

Since the declarator "serves as a function prototype" even though
it does not include the function's return type, a prototype does
not include the return type.

... and yet, there seem to be contradictions. 6.2.1/2:

"[...] (A _function prototype_ is a declaration of
a function that declares the types of its parameters.)"

A function declaraTION (not declaraTOR) *does* include the return
type, so this passage says you're right and I'm wrong. Hard to
say which paragraph wins out.

But then there's 6.7.5.3/1:

"A function declarator shall not specify a return type
that is a function type or an array type."

.... implying that a declaraTOR does incorporate the return type
(or the constraint would be vacuous). I think this must be a
typo for declaraTION, because the grammar of 6.7/1 shows that
the return type is part of the declaration-specifiers, separate
from the init-declarator-list that eventually contains the
declarator. Hence, according to the grammar the function's
return type is not part of the declaraTOR, but is part of the
declaraTION.

Other sections of the Standard (6.5.2.2, 7.1.2/1) speak of
function types that "include" prototypes, suggesting that the
prototype is "less than" the complete declaration of the function,
which would feature the return type. That's suggestive, maybe,
but I don't think it's conclusive.

There are also some references to a "function prototype
declarator," a term that doesn't seem to appear in the grammar.

The whole business turns out to be much more confusing (and
even contradictory) than I had thought! Given the uncertainty,
I was rash to jump all over Pemo for misusing (I thought) the
word "prototype;" I apologize to him.
 
K

Keith Thompson

Eric Sosman said:
(e-mail address removed) wrote: [...]
[...]
So the return type is not part of the prototype ?
Why not ?

"Why not?" Because of 6.9.1/7:

"The declarator in a function definition specifies the
name of the function being defined and the identifiers
of its parametsrs. [Note omission of return type.] If
the declarator includes a parameter type list, [...]
such a declarator also serves as a function prototype
for later calls to the same function [...]"

Since the declarator "serves as a function prototype" even though
it does not include the function's return type, a prototype does
not include the return type.

... and yet, there seem to be contradictions. 6.2.1/2:

"[...] (A _function prototype_ is a declaration of
a function that declares the types of its parameters.)"

A function declaraTION (not declaraTOR) *does* include the return
type, so this passage says you're right and I'm wrong. Hard to
say which paragraph wins out.

Since 6.2.1p2 has "function prototype" in italics, it's the definition
of the term, so I'd say it wins out.

Possibly 6.8.1p7 is badly worded.
 
K

Keith Thompson

lovecreatesbeauty said:
int a, b, foo( int );


int foo( ); /*int foo( int );*/

It's not a function use/call, foo() occurs inside a declaration. It's a
function prototype declaration.

It's a function declaration, but not a prototype. To be a prototype,
it would have to declare the types of the parameters.

With empty parentheses, it specifies that foo takes an fixed but
unspecified number and type(s) of arguments. (To specify that it
takes no arguments, you'd declare "int foo(void)".)

The declaration is legal, but since there's already a visible
prototype for foo, it's completely useless. Putting a function
declaration in a list along with object declarations is legal, but
very odd style. Re-declaring a function inside a function is also
legal, but it's almost never a good idea.
 
J

Jack Klein

But it's a declaration that deviates from the declaration
given in line 1. There's no function "foo" defined without
any parameters, so why is the declaration from line 8
accepted by a compiler?

Part of your confusion is based on a misunderstanding of this:

int foo(int);

....regardless of the fact that it as at block scope rather than file
scope.

The declaration (not prototype) above declares foo to be a function
that returns an int and accepts an unspecified but fixed number and
type of arguments.

It most specifically is NOT a prototype for a function that takes no
arguments. In another language that stole much of an earlier version
of C, these two declarations are equivalent:

int foo();
int foo(void);

....that is not the case in real, genuine, C.
 
K

Keith Thompson

Jack Klein said:
Part of your confusion is based on a misunderstanding of this:

int foo(int);

...regardless of the fact that it as at block scope rather than file
scope.

The declaration (not prototype) above declares foo to be a function
that returns an int and accepts an unspecified but fixed number and
type of arguments.

"int foo(int);" is both a declaration and a prototype.

The declaration in the original code was "int foo();", which is a
declaration but not a prototype. (Actually it was "int a, b, foo();",
which is an odd way of saying the same thing.)
It most specifically is NOT a prototype for a function that takes no
arguments. In another language that stole much of an earlier version
of C, these two declarations are equivalent:

int foo();
int foo(void);

...that is not the case in real, genuine, C.

Ok, so I think you *meant* to say "int foo();" rather than "int foo(int);".
 
L

lovecreatesbeauty

Keith said:
It's a function declaration, but not a prototype. To be a prototype,
it would have to declare the types of the parameters.

With empty parentheses, it specifies that foo takes an fixed but
unspecified number and type(s) of arguments. (To specify that it
takes no arguments, you'd declare "int foo(void)".)

I remember that int f(){}; int f2(); are obsolete.

Function prototype is a kind of declaration, right? The function
getchar has no parameters. The code includes <stdio.h> before calls it,
does not it? I think this is giving the function prototype.
 
K

Keith Thompson

lovecreatesbeauty said:
I remember that int f(){}; int f2(); are obsolete.

Function prototype is a kind of declaration, right?

Right. Specifically, it's "a declaration of a function that declares
the types of its parameters" (quoting the standard).

Now that I think about it, there's a small hole in that definition
for parameterless functions. "int foo(void)" is a prototype, but
"int foo()" is not, but one could argue that neither one "declares
the types of its parameters"; rather, one specifies that there are
no parameters and the other doesn't.
The function
getchar has no parameters. The code includes <stdio.h> before calls it,
does not it? I think this is giving the function prototype.

Correct, the prototype is in <stdio.h>.
 

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

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top