A couple of questions re. the function prototype

R

Rob Somers

Hey people,

I read a good thread on here regarding the reason why we use function
prototypes, and it answered most of my questions, but I wanted to
double check on a couple of things, as I am writing something up on
functions, and I don't like writing about things I am not sure about.

Ok, then, here we go:

I initially thought that one would only really need to use a function
prototype if the type the function returned was not an int - I was
under the impression that if there was no prototype, the compiler
would assume it was an int. However, my compiler (gcc) squawks at me
if I do not use a prototype even if the function returns an int. So
this makes me wonder if I was wrong in thinking that I did not have to
use a prototype for a function returning an int. And now that I think
about it, the prototype does more than allow the compiler to check for
a return type perhaps? It also allows for it to check that the
arguments at the function call are of the same type as the parameters
of the function? (Yes I am still relatively new to C) So the
question is this: Is it proper (as regarding making portable
programs) to *always* use a function prototype? And then my second
question is, If the actual function serves as a prototype also, why
not just put all the functions before main()? I am not trying to
start flames here BTW, if this is potential flame material - I am
simply looking for your thoughts, as I really don't know that much
about the subject. Thanks

Rob Somers
 
S

Sheldon Simms

Hey people,

I read a good thread on here regarding the reason why we use function
prototypes, and it answered most of my questions, but I wanted to
double check on a couple of things, as I am writing something up on
functions, and I don't like writing about things I am not sure about.

Ok, then, here we go:

I was under the impression that if there was no prototype, the compiler
would assume it was an int. However, my compiler (gcc) squawks at me

This style of C has been outdated for more than 10 years. If you
are using books that suggest this, you need to update your books.
In fact, omitting the return type of a function is no longer legal C,
so be thankful that gcc is complaining.
this makes me wonder if I was wrong in thinking that I did not have to
use a prototype for a function returning an int.

Correct, you were wrong.
And now that I think
about it, the prototype does more than allow the compiler to check for
a return type perhaps? It also allows for it to check that the
arguments at the function call are of the same type as the parameters
of the function?

Absolutely correct.
Is it proper (as regarding making portable
programs) to *always* use a function prototype?

Yes it is.
And then my second
question is, If the actual function serves as a prototype also, why
not just put all the functions before main()?

I do exactly that most of the time, assuming that by "all" you mean
"all of the functions that happen to be in the same source file as
main()".

C programs are usually a collection of source files, each of which
contains some number of function definitions. Some functions are
meant to be exported and their prototypes are included in an associated
header file for inclusion in other source files. Some functions are
not meant to be exported. They are defined with the keyword static
and as long as callers come after callees in the source file, there
is no need for an "extra" prototype.

-Sheldon
 
M

Mark Gordon

On 9 Nov 2003 09:25:26 -0800
Hey people,

I read a good thread on here regarding the reason why we use function
prototypes, and it answered most of my questions, but I wanted to
double check on a couple of things, as I am writing something up on
functions, and I don't like writing about things I am not sure about.

Ok, then, here we go:

I initially thought that one would only really need to use a function
prototype if the type the function returned was not an int - I was
under the impression that if there was no prototype, the compiler
would assume it was an int.

Don't forget you can do something like:
float func();

which does not provide a prototype (if I remember my definitions
correctly) since it does not specify the parameter types.

However, it is generally good practise to ensure that there is a
prototype in scope for all calls since it allows the compiler to ensure
that the parameters are of compatible types.
However, my compiler (gcc) squawks at me
if I do not use a prototype even if the function returns an int. So
this makes me wonder if I was wrong in thinking that I did not have to
use a prototype for a function returning an int. And now that I think
about it, the prototype does more than allow the compiler to check for
a return type perhaps? It also allows for it to check that the
arguments at the function call are of the same type as the parameters
of the function? (Yes I am still relatively new to C) So the
question is this: Is it proper (as regarding making portable
programs) to *always* use a function prototype?

It is good practise since it helps the compiler to find errors for you.
Anything that helps the compiler find errors for you is a good idea.
And then my second
question is, If the actual function serves as a prototype also, why
not just put all the functions before main()? I am not trying to
start flames here BTW, if this is potential flame material - I am
simply looking for your thoughts, as I really don't know that much
about the subject. Thanks

Yes, the function definition serves as a prototype. Some people believe
in always defining a function before it is first used, some people
believe in providing a set of prototypes at the start of the file.

Also, when you split a program into multiple source files you should use
header files to provide the prototypes for functions defined in one file
and used in another and include the header in the file that defines the
function as well as the one that uses it to ensure consistency
throughout.
 
O

osmium

Rob said:
And then my second
question is, If the actual function serves as a prototype also, why
not just put all the functions before main()? I am not trying to
start flames here BTW, if this is potential flame material - I am
simply looking for your thoughts, as I really don't know that much
about the subject. Thanks

I do write and debug code that way. But when it is done, or as done as
anything ever gets, I move the definition to the end of main and write
prototypes, I know exactly what they are now and most of them are going to
stay that way.

Why? It's a documentation aid. If you were to look for some obscure hamlet
in some obscure country on a map of the world it would be hard to find. Two
maps are better than one. A list of well named functions and a bit of luck
and you might be able to get some idea as to how this beast is organized.
 
C

CBFalconer

Rob said:
.... snip ...

question is this: Is it proper (as regarding making portable
programs) to *always* use a function prototype? And then my
second question is, If the actual function serves as a prototype
also, why not just put all the functions before main()? I am

Yes. and yes. In fact this (declare before using) method is much
safer, because there is no separate prototype to maintain. It
also means that you always know where to look for a function body,
i.e. earlier in the file than where it is used.

This means a separate prototype is only needed when mutual
recursion exists, or when it is necessary to export a function for
use elsewhere. In the export case, the prototype belongs in the
include file for that module. Lacking an export requirement, the
function is best declared static to restrict its visibility. It
will be a great comfort, in the far future when maintaining the
code, to know that the function has no uses outside the current
file.
 
P

Peter Nilsson

...Is it proper (as regarding making portable
programs) to *always* use a function prototype?

Yes. Indeed, C99 removed implicit int and has deprecated
non-prototyped function declarators.
 
R

Rob Somers

Mark Gordon said:
On 9 Nov 2003 09:25:26 -0800


Don't forget you can do something like:
float func();

which does not provide a prototype (if I remember my definitions
correctly) since it does not specify the parameter types.

However, it is generally good practise to ensure that there is a
prototype in scope for all calls since it allows the compiler to ensure
that the parameters are of compatible types.


It is good practise since it helps the compiler to find errors for you.
Anything that helps the compiler find errors for you is a good idea.


Yes, the function definition serves as a prototype. Some people believe
in always defining a function before it is first used, some people
believe in providing a set of prototypes at the start of the file.

Also, when you split a program into multiple source files you should use
header files to provide the prototypes for functions defined in one file
and used in another and include the header in the file that defines the
function as well as the one that uses it to ensure consistency
throughout.

This has all been very instructive for me - thank you for your
responses. I have been working through K&R2, though I am aware that
it is not exactly 'ANSI C' anymore, so I know I sometimes need to
check and be sure what I am learning is up to date.

So another question then - in K&R2 they say that the names of the
parameters in the function prototype need not agree with the names of
the parameters in the function - or alternatively you do not need to
use any names at all in the prototype, provided you put in the data
types. Is this still legal? Now my thinking is this; even if it were
still legal to do this sort of thing with a prototype, it seems like a
bad practice in that it makes things more confusing when names don't
match.

Rob Somers
 
C

Chris Torek

... in K&R2 they say that the names of the
parameters in the function prototype need not agree with the names of
the parameters in the function - or alternatively you do not need to
use any names at all in the prototype, provided you put in the data
types. Is this still legal?

It is. That is:

char *foo(int);

is a valid prototype, and even:

char *foo(int zag);
char *foo(int gaz) { /* some code here */ }

is fine as far as standard syntax and semantics go.
Now my thinking is this; even if it were
still legal to do this sort of thing with a prototype, it seems like a
bad practice in that it makes things more confusing when names don't
match.

I think one might consider it the moral equivalent of code like
this:

/* The foo function takes no arguments. The return value has
type double. */
char *foo(int zag) {
static char buf[100];

sprintf(buf, "%d", zag);
return buf;
}

Here the comment clearly contradicts the code. Which one is "what
the programmer meant to write"? In general, programs need to be
written for *two* readers: the computer/compiler, which reads
precisely what is there according to the rules of the language;
and the human-being/programmer, who needs to find the *intent*,
whether or not that is precisely what is there. In particular,
bugs generally occur when the intent and the actuality differ
(though sometimes they occur when the programmer's intent is
incorrect, too; and on rare occasion, it is just barely possible
for one error to cancel out the other).

In any case, I believe comments should generally express "goals
and reasons" for code, rather than the direct mechanics thereof.
Moreover, variable and function names are a form of comment. After
all, a compiler does not care if you name all your variables "a0001",
"a0002", "a0003", and so on. If a name like "number_of_ravens" is
not meant to mean something to a compiler, then who *is* it meant
for?
 
D

Dan Pop

In said:
I initially thought that one would only really need to use a function
prototype if the type the function returned was not an int - I was
under the impression that if there was no prototype, the compiler
would assume it was an int.

Are you *sure* you understand the difference between function declaration
and function prototype?

Not every function declaration is a function prototype and not every
function requires a prototype declaration and the return type is only
a minor part of the issue.

Dan
 
J

John Bode

Hey people,

I read a good thread on here regarding the reason why we use function
prototypes, and it answered most of my questions, but I wanted to
double check on a couple of things, as I am writing something up on
functions, and I don't like writing about things I am not sure about.

Ok, then, here we go:

I initially thought that one would only really need to use a function
prototype if the type the function returned was not an int - I was
under the impression that if there was no prototype, the compiler
would assume it was an int.

That applies to a function *declaration*. Not all function
declarations are prototypes:

int f(); /* not a prototype */
int f(void); /* prototype */

double g (a, b, c); /* not a prototype */
double g (int a, char *b, float c); /* prototype */

If no *declaration* is in scope, then the function is assumed to
return int:

int main (void)
{
int a;

a = f(0); /* no declaration in scope,
f() is assumed to return int */
return 0;
}

The following has a declaration in scope, but no prototype:

int main (void)
{
int a, f();

a = f(0); /* f() is declared as returning int */
return 0;
}

The following has a prototype in scope:

int main (void)
{
int a, f(int);

a = f(0); /* f is declared as taking a single
int parameter and returning int */
return 0;
}
However, my compiler (gcc) squawks at me

Error or warning? I just get a warning.
if I do not use a prototype even if the function returns an int. So
this makes me wonder if I was wrong in thinking that I did not have to
use a prototype for a function returning an int.

You don't *have* to have a declaration in scope for a function that
returns int, but that's not a safe coding practice, and you could wind
up shooting yourself in the foot. That's why gcc issues a warning.
And now that I think
about it, the prototype does more than allow the compiler to check for
a return type perhaps? It also allows for it to check that the
arguments at the function call are of the same type as the parameters
of the function?

Exactly. That's the reasoning behind a prototype.
(Yes I am still relatively new to C) So the
question is this: Is it proper (as regarding making portable
programs) to *always* use a function prototype?

Yes. There is no good reason (beyond using an ancient compiler that
doesn't support them) *not* to use prototypes. It's not a portability
issue as much as it is a correctness and maintenance issue.
And then my second question is, If the actual function serves as a prototype
also, why not just put all the functions before main()?

Where feasible, that's how I code; functions are defined (in prototype
form) before they are referenced. However, any serious project is
going to be split up among several files, so prototypes are necessary
when using functions defined in other files.

Also, remember that a function definition may not necessarily be in
prototype form; the old K&R-style of

int foo (a, b)
int a;
double b;
{
...
}

does not contain a prototype. A function definition of the style

int foo (int a, double b)
{
...
}

does contain a prototype.
 
R

Rob Somers

Are you *sure* you understand the difference between function declaration
and function prototype?

Not every function declaration is a function prototype and not every
function requires a prototype declaration and the return type is only
a minor part of the issue.

Dan

Hmmm... Now you have raised some thoughts for me... A function
declaration is not a function. I will make a stab at this, and then
you can correct anything that is wrong if you wish; A function
prototype is a 'shell' of a real function and as such does not have
the expressions and statements that the actual function does. The
prototype is there to aid the compiler with type checking. Hope that
is not way out there, as I hate to sound uber ignorant. I am here to
learn though.

Another question, somewhat related. Say you had 3 parameters in a
function, and they were all float type - you can't just go something
like this, can you?:

int foo( float x, y, z )
{
blah blah
}

My understanding is that you have to explicitly name the data types
and for each one, like this:

int foo( float x, float y, float z )
{
blah blah
}

Am I correct?
 
R

Rob Somers

Are you *sure* you understand the difference between function declaration
and function prototype?

Not every function declaration is a function prototype and not every
function requires a prototype declaration and the return type is only
a minor part of the issue.

Dan

Oops - I made a typo on the last post

I said something like 'a function declaration is not a function'

I meant a function declaration is not a function prototype

Rob
 
I

Irrwahn Grausewitz

(e-mail address removed) (Dan Pop) wrote in message news:<[email protected]>...

Hmmm... Now you have raised some thoughts for me...
//> A function
//> declaration is not a function.
RS-edit> A function declaration is not a function prototype.

Not quite: A function declaration is not /necessarily/ a function
prototype; consider:

int foo(); /* A function declaration which is /not/ a prototype */
int foo(int); /* A function declaration which /is/ a prototype */
I will make a stab at this, and then
you can correct anything that is wrong if you wish; A function
prototype is a 'shell' of a real function and as such does not have
the expressions and statements that the actual function does.

C99 states: "A function prototype is a declaration of a function that
declares the types of its parameters."
The
prototype is there to aid the compiler with type checking.

.... and argument promotion, etc.
Hope that
is not way out there, as I hate to sound uber ignorant. I am here to
learn though.

Another question, somewhat related. Say you had 3 parameters in a
function, and they were all float type - you can't just go something
like this, can you?:

int foo( float x, y, z )
{
blah blah
}

Correct, you can't.
My understanding is that you have to explicitly name the data types
and for each one, like this:

int foo( float x, float y, float z )
{
blah blah
}

Am I correct?

Yes. It follows from the definition of 'parameter-type-list' in
the C grammar.

Regards
 
D

Dan Pop

In said:
Oops - I made a typo on the last post

I said something like 'a function declaration is not a function'

I meant a function declaration is not a function prototype

You were wrong, anyway. A function declaration may or may not be a
prototype. Read the apropriate chapter in your favourite C book, the
issue is too basic to be discussed here.

Dan
 
R

Ravi Uday

[ snip ]
That applies to a function *declaration*. Not all function
declarations are prototypes:

int f(); /* not a prototype */
int f(void); /* prototype */

double g (a, b, c); /* not a prototype */
double g (int a, char *b, float c); /* prototype */

Fine
If no *declaration* is in scope, then the function is assumed to
return int:

int main (void)
{
int a;

a = f(0); /* no declaration in scope,
f() is assumed to return int */
return 0;
}
Fine
The following has a declaration in scope, but no prototype:

int main (void)
{
int a, f();

a = f(0); /* f() is declared as returning int */
return 0;
}
But when i execute it says "unresolved external symbol _f"
The following has a prototype in scope:

int main (void)
{
int a, f(int);

a = f(0); /* f is declared as taking a single
int parameter and returning int */
return 0;
}
[ snip ]

I think i got myself confused. What does the terms *declaration*,
*definition* mean. I think i know what a *prototype* is !

- Ravi
 
R

Richard Heathfield

Ravi said:
I think i got myself confused. What does the terms *declaration*,
*definition* mean. I think i know what a *prototype* is !

int foo(); /* declaration */
int foo(int a, char **v); /* declaration that names its parameters - i.e. a
prototype */

int foo(int a, char **v)
{
/* declaration that introduces a function body - i.e. a definition. Also
names its parameters. Therefore, also a prototype. */


HTH. HAND.
 
J

John Bode

[ snip ]
That applies to a function *declaration*. Not all function
declarations are prototypes:

int f(); /* not a prototype */
int f(void); /* prototype */

double g (a, b, c); /* not a prototype */
double g (int a, char *b, float c); /* prototype */
Fine

If no *declaration* is in scope, then the function is assumed to
return int:

int main (void)
{
int a;

a = f(0); /* no declaration in scope,
f() is assumed to return int */
return 0;
} Fine

The following has a declaration in scope, but no prototype:

int main (void)
{
int a, f();

a = f(0); /* f() is declared as returning int */
return 0;
}
But when i execute it says "unresolved external symbol _f"

Sorry, these were just quick examples of what constituted a prototype;
they weren't meant to be compiled and run, so I didn't bother
providing a definition for f().
The following has a prototype in scope:

int main (void)
{
int a, f(int);

a = f(0); /* f is declared as taking a single
int parameter and returning int */
return 0;
}
[ snip ]

I think i got myself confused. What does the terms *declaration*,
*definition* mean. I think i know what a *prototype* is !

- Ravi

A function *declaration* introduces a reference to a function that is
actually defined elsewhere. It specifies *at least* the function name
and its return type:

int f();

A function *definition* introduces a new function and provides the
return type, number and type of formal parameters, visibility (subject
for another day), and the code that is to be executed when the
function is called:

/*
** Prototype syntax
*/
int f (int x, int y)
{
return 2 * x / y;
}

/*
** Older, K&R-style, non-prototype syntax
*/
int f (x, y)
int x;
int y;
{
return 2 * x / y;
}

A function *prototype* is a function declaration or definition using
the prototype syntax; that is, the number and type of parameters are
specified in the parameter list:

int f (int x, int y); /* prototype declaration */

Here's a hopefully complete example that illustrates all this:

#include <stdio.h>

int main (void)
{
int x, y;
int f(int, int); /* declaration, prototype form */

printf ("Gimme a couple of numbers: ");
scanf ("%d %d", &x, &y);

printf ("Result is %d\n", f (x, y)); /* call to f() */

return 0;
}

int f (int x, int y) /* definition, prototype form */
{
return 2 * x / y;
}
 
D

Dave Thompson

Yes. Indeed, C99 removed implicit int and has deprecated
non-prototyped function declarators.

True as far as you go, but not complete or fully responsive.

C99 removed implicit int, which applies to declarations or definitions
that are written; it also removed implicit function declaration (as
taking unspecified default-promoted arguments and returning int) which
was the OP's case.

C*89* deprecated nonprototype function declarations *and definitions*,
which unlike for objects are syntactically separate although
semantically a definition is also a declaration; C99 retained this
deprecation unchanged.

- David.Thompson1 at worldnet.att.net
 
A

Alex

Oops - I made a typo on the last post
I said something like 'a function declaration is not a function'
I meant a function declaration is not a function prototype

void foo(); /* declaration only */
void bar(int, int); /* declaration and prototype */

A prototype is a special kind of declaration that contains
parameter types.

Alex
 
D

Dan Pop

In said:
void foo(); /* declaration only */
void bar(int, int); /* declaration and prototype */

It's actually "non-prototype declaration" (or "old style declaration")
and "prototype declaration". Plain "declaration" means either of the two.

Dan
 

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

Forum statistics

Threads
473,772
Messages
2,569,593
Members
45,111
Latest member
KetoBurn
Top