function prototype vs function declaration

While prepating a content for a C course,I made section on function
prototypes.
Could you kindly provide me your comments on its correctness. Thank you !

Q12: What is the difference between a function prototype and a function
declaration?

If you get this right, you must have done fair amount of research on C
programming beginning with "K&R" C. It turns out that function declarations
and function prototypes are the same thing in standard C. In K&R C a
function declaration did not need to have the types of its arguments to be
specified.

Thus a declaration like:

int Spi_Tx();

was perfectly acceptable, even though its definition was infact:

int Spi_Tx(uint8 TragetId,uint8 byteArray[],uint16 count)

{

}

It was easy for programmers to call the function with incorrect
parameters which needless to say had disastrous runtime consequences. Thus
ANSI C mandates function prototypes as the method for function declaration.

Advertisements

"Richard Heathfield" <> wrote in message
news:...
> Ravishankar S said:
>
> <snip>
>
> > It turns out that function
> > declarations and function prototypes are the same thing in standard C.
>
> No, it doesn't.
>
> It is true that all function prototypes are function declarations, but it
> is not true that all function declarations are function prototypes.
>
> <snip>

Ravishankar S wrote:
>
> "Richard Heathfield" <> wrote in message
> news:...
>> Ravishankar S said:
>>
>> <snip>
>>
>> > It turns out that function
>> > declarations and function prototypes are the same thing in standard
>> > C.
>>
>> No, it doesn't.
>>
>> It is true that all function prototypes are function declarations,
>> but it is not true that all function declarations are function
>> prototypes.
>>
>> <snip>
>
> an example would help here.

int fx();

This is a function declaration, but not a prototype. In fact, argument
checking is turned of for functions declared like this. This is for
backwards compatibility and not recommended for new code. Use:

It turns out that there is no difference between function declarations and
function prototypes as far as modern use of C is concerned. When a function
is declared, the number and types of its arguments are also naturally
specified. Such a declaration is also a function prototype.

But it is also allowed to declare a function without specifying its
arguments. In this case the compiler turns off argument checking at the
point of its call. This is meant for backward compatibility (K&R C) should
not be used in normal code. For example:

int fx(); /* declaration , but not a function prototype */

int testFx(void)

{

/* Compiler will not check for argument type match */

if (fx(5) == 10)

{

return 11;

}

return 15;

}

/* Will not get the required arguments ! */

int fx(double a,double b,double c)

{

if((a + b) > c)

return 10;

else

return 11;

}

Thus it is easy for programmers to call the function with incorrect
parameters which needless to say has disastrous runtime consequences. ANSI C
mandates function prototypes as the method for function declaration.

<snip>
>
> My amended article would be:
>
> It turns out that there is no difference between function declarations
> and
> function prototypes as far as modern use of C is concerned.

I think you should stop writing tutorials and start reading them. There is
a very important distinction between a declaration and a prototype, and
you do your readers a disservice by not making the distinction clear.

What's more, there are (rather recondite) circumstances where you could
conceivably need to eschew the prototype form - I'm thinking particularly
of arrays of pointer to function where not all the functions have the same
type. It is important to know when to use the prototype form (i.e. nearly
always) and when it *might* be a good idea not to.

"Richard Heathfield" <> wrote in message
news:...
> Ravishankar S said:
>
> <snip>
> >
> > My amended article would be:
> >
> > It turns out that there is no difference between function declarations
> > and
> > function prototypes as far as modern use of C is concerned.
>
> I think you should stop writing tutorials and start reading them. There is
> a very important distinction between a declaration and a prototype, and
> you do your readers a disservice by not making the distinction clear.

I am making that distinction.Its only the perception that differs. I was
infact wondering whether I should make that
sentence ("there is a minor yet important difference between function
declaration and function prototype"). But I changed
since I have to make its importance clear.

I am sure 90/100 C progrmmers are not aware of this distiction given now
that function
prototypes are common.
>
> What's more, there are (rather recondite) circumstances where you could
> conceivably need to eschew the prototype form - I'm thinking particularly
> of arrays of pointer to function where not all the functions have the same
> type. It is important to know when to use the prototype form (i.e. nearly
> always) and when it *might* be a good idea not to.
>
I was thinking that my conclusions are fairly accurate!
But I cannot help but note that what you have mentioned may also be achieved
by using void pointer's.

Ravishankar S wrote:
>
> "Richard Heathfield" <> wrote in message
> news:...
>> Ravishankar S said:
>>
>> <snip>
>> >
>> > My amended article would be:
>> >
>> > It turns out that there is no difference between function
>> > declarations and
>> > function prototypes as far as modern use of C is concerned.
>>
>> I think you should stop writing tutorials and start reading them.
>> There is a very important distinction between a declaration and a
>> prototype, and you do your readers a disservice by not making the
>> distinction clear.
>
> I am making that distinction.Its only the perception that differs. I
> was infact wondering whether I should make that
> sentence ("there is a minor yet important difference between function
> declaration and function prototype"). But I changed
> since I have to make its importance clear.
>
> I am sure 90/100 C progrmmers are not aware of this distiction given
> now that function
> prototypes are common.

However it is better to accurately explain the language as it is
formalised rather than as it might be commonly used. Flushing stdin,
voiding main and using gets seem to be distressingly common in real
world usage, but a tutorial that uses them other than to describe their
dangers, would be considered of very low quality.
>> What's more, there are (rather recondite) circumstances where you
>> could conceivably need to eschew the prototype form - I'm thinking
>> particularly of arrays of pointer to function where not all the
>> functions have the same type. It is important to know when to use the
>> prototype form (i.e. nearly always) and when it *might* be a good
>> idea not to.
>>
> I was thinking that my conclusions are fairly accurate!
> But I cannot help but note that what you have mentioned may also be
> achieved by using void pointer's.

No. void pointers are quite different from function pointers. Please
read a good textbook before continuing on your tutorial.

> However it is better to accurately explain the language as it is
> formalised rather than as it might be commonly used. Flushing stdin,
> voiding main and using gets seem to be distressingly common in real
> world usage, but a tutorial that uses them other than to describe their
> dangers, would be considered of very low quality.

Point taken. Though this not of the same stature are of writing "void main"
and "fflush(stdin)".
> > I was thinking that my conclusions are fairly accurate!
> > But I cannot help but note that what you have mentioned may also be
> > achieved by using void pointer's.
>
> No. void pointers are quite different from function pointers. Please
> read a good textbook before continuing on your tutorial.

Please recommend me a good book, other than K&R which covers these points.
Thank you.

If I am not mistaken a void* must be capabale of storing any pointer
(generic pointer) including
a pointer to a function...

Ravishankar S said:
> If I am not mistaken a void* must be capabale of storing any pointer
> (generic pointer) including
> a pointer to a function...

You are mistaken.

See 3.2.2.3 of C89 - "A pointer to void may be converted to or from a
pointer to any incomplete or object type. A pointer to any incomplete or
object type may be converted to a pointer to void and back again; the
result shall compare equal to the original pointer." - or the C99
equivalent, 6.3.2.3. The absence of a definition of the behaviour on
converting a function pointer to void * or back means that that behaviour
is undefined.

Ravishankar S wrote:
....
> If I am not mistaken a void* must be capabale of storing any pointer
> (generic pointer) including a pointer to a function...

You are mistaken. And I'd be very surprised if K&R 2 got that wrong. The
relevant clause is 6.3.2.3p1:

"A pointer to void may be converted to or from a pointer to any
incomplete or object type. A pointer to any incomplete or object type
may be converted to a pointer to void and back again; the result shall
compare equal to the original pointer."

A function type is not an incomplete or object type. Therefore, this
clause does not cover pointers to function types; and there is no other
clause which does cover them.

However, p8 says:

"A pointer to a function of one type may be converted to a pointer to a
function of another type and back again; the result shall compare equal
to the original pointer. If a converted pointer is used to call a
function whose type is not compatible with the pointed-to type, the
behavior is undefined."

Therefore, any pointer to function type can be used for the same purpose
with pointers to functions that void* is used for with pointers to
object types. I generally would prefer "void (*)()" for this purpose,
because it's pretty much the most generic type.

Ravishankar S wrote:
>
>> However it is better to accurately explain the language as it is
>> formalised rather than as it might be commonly used. Flushing stdin,
>> voiding main and using gets seem to be distressingly common in real
>> world usage, but a tutorial that uses them other than to describe
>> their dangers, would be considered of very low quality.
>
> Point taken. Though this not of the same stature are of writing "void
> main" and "fflush(stdin)".

Perhaps.
>> > I was thinking that my conclusions are fairly accurate!
>> > But I cannot help but note that what you have mentioned may also be
>> > achieved by using void pointer's.
>>
>> No. void pointers are quite different from function pointers. Please
>> read a good textbook before continuing on your tutorial.
>
> Please recommend me a good book, other than K&R which covers these
> points. Thank you.

C: A Reference Manual by Harbison & Steele
<http://careferencemanual.com/>
> If I am not mistaken a void* must be capabale of storing any pointer
> (generic pointer) including a pointer to a function...

No. A void pointer can only store pointers to object and incomplete
types. Conversion between function and void pointer types is undefined.
Also there is no "generic" function pointer type.

> > If I am not mistaken a void* must be capabale of storing any pointer
> > (generic pointer) including
> > a pointer to a function...
>
> You are mistaken.
>
> See 3.2.2.3 of C89 - "A pointer to void may be converted to or from a
> pointer to any incomplete or object type. A pointer to any incomplete or
> object type may be converted to a pointer to void and back again; the
> result shall compare equal to the original pointer." - or the C99
> equivalent, 6.3.2.3. The absence of a definition of the behaviour on
> converting a function pointer to void * or back means that that behaviour
> is undefined.

Thank you. very interesting and enlightening. Does this as corollary mean
that pointers of the type
<type> (*fp)() are legal generic function pointers..??

James Kuyper said:
> Ravishankar S wrote:
> ...
>> If I am not mistaken a void* must be capabale of storing any pointer
>> (generic pointer) including a pointer to a function...
>
> You are mistaken. And I'd be very surprised if K&R 2 got that wrong.

Brace yourself, then, as you read pp93, 103, 120 and 199, none of which
make it clear that function pointers are not included in the void * magic.
The closest approach is in the tiny-type text on page 199, which
incorrectly singles out object pointers (and thus ignores incomplete
pointers).

Richard Heathfield wrote:
> James Kuyper said:
>
>> Ravishankar S wrote:
>> ...
>>> If I am not mistaken a void* must be capabale of storing any pointer
>>> (generic pointer) including a pointer to a function...
>> You are mistaken. And I'd be very surprised if K&R 2 got that wrong.
>
> Brace yourself, then, as you read pp93, 103, 120 and 199, none of which
> make it clear that function pointers are not included in the void * magic.
> The closest approach is in the tiny-type text on page 199, which
> incorrectly singles out object pointers (and thus ignores incomplete
> pointers).

I learned C from K&R 1st edition (2nd edition was still years in the
future at that time), and it was excellent. I've never actually read
K&R2; I rely on the standard itself whenever I have a question. I'm a
little disappointed to hear that K&R 2 falls short.

Ravishankar S wrote:
>> > If I am not mistaken a void* must be capabale of storing any
>> > pointer (generic pointer) including
>> > a pointer to a function...
>>
>> You are mistaken.
>>
>> See 3.2.2.3 of C89 - "A pointer to void may be converted to or from a
>> pointer to any incomplete or object type. A pointer to any
>> incomplete or object type may be converted to a pointer to void and
>> back again; the result shall compare equal to the original pointer."
>> - or the C99 equivalent, 6.3.2.3. The absence of a definition of the
>> behaviour on converting a function pointer to void * or back means
>> that that behaviour is undefined.
>
> Thank you. very interesting and enlightening. Does this as corollary
> mean that pointers of the type
> <type> (*fp)() are legal generic function pointers..??

Any function pointer type can hold losslessly, the value of any other
function pointer type, but when you deference the pointer to actually
invoke a function, the type of that function and the type of the
function pointer used for calling it must match. Otherwise the
behaviour is undefined.
> Finally, any C text book that covers these points explicitly ?

Both _K&R2_ and _C: A Reference Manual_ do so. The fifth edition of the
latter is updated to explain the C99 standard while K&R2 knows only
about the C90 standard.

Share This Page

Welcome to The Coding Forums!

Welcome to the Coding Forums, the place to chat about anything related to programming and coding languages.

Please join our friendly community by clicking the button below - it only takes a few seconds and is totally free. You'll be able to ask questions about coding or chat with the community and help others.
Sign up now!