Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #17289 > unrolled thread

Function Prototypes: Necessary or just good practice?

Started by/dev/phaeton <blahbleh666@no_more_spam.hotmail.com>
First post2012-02-13 23:05 -0600
Last post2012-02-15 08:31 -0500
Articles 17 — 10 participants

Back to article view | Back to comp.lang.c


Contents

  Function Prototypes: Necessary or just good practice? /dev/phaeton <blahbleh666@no_more_spam.hotmail.com> - 2012-02-13 23:05 -0600
    Re: Function Prototypes: Necessary or just good practice? Johann Klammer <klammerj@NOSPAM.a1.net> - 2012-02-14 07:31 +0100
      Re: Function Prototypes: Necessary or just good practice? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-02-14 13:14 +0000
        Re: Function Prototypes: Necessary or just good practice? Ralf Damaschke <rwspam@gmx.de> - 2012-02-14 16:20 +0000
        Re: Function Prototypes: Necessary or just good practice? Peter Nilsson <airia@acay.com.au> - 2012-02-14 13:47 -0800
          Re: Function Prototypes: Necessary or just good practice? James Kuyper <jameskuyper@verizon.net> - 2012-02-14 17:01 -0500
            Re: Function Prototypes: Necessary or just good practice? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-02-14 22:35 +0000
              Re: Function Prototypes: Necessary or just good practice? James Kuyper <jameskuyper@verizon.net> - 2012-02-14 17:51 -0500
                Re: Function Prototypes: Necessary or just good practice? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-02-15 00:06 +0000
            Re: Function Prototypes: Necessary or just good practice? Peter Nilsson <airia@acay.com.au> - 2012-02-14 20:27 -0800
              Re: Function Prototypes: Necessary or just good practice? Keith Thompson <kst-u@mib.org> - 2012-02-14 22:24 -0800
    Re: Function Prototypes: Necessary or just good practice? Stephen Sprunk <stephen@sprunk.org> - 2012-02-14 01:18 -0600
    Re: Function Prototypes: Necessary or just good practice? Philip Lantz <prl@canterey.us> - 2012-02-14 00:05 -0800
    Re: Function Prototypes: Necessary or just good practice? Kaz Kylheku <kaz@kylheku.com> - 2012-02-14 09:09 +0000
      Re: Function Prototypes: Necessary or just good practice? /dev/phaeton <blahbleh666@no_more_spam.hotmail.com> - 2012-02-14 23:51 -0600
        Re: Function Prototypes: Necessary or just good practice? Kaz Kylheku <kaz@kylheku.com> - 2012-02-15 06:36 +0000
        Re: Function Prototypes: Necessary or just good practice? James Kuyper <jameskuyper@verizon.net> - 2012-02-15 08:31 -0500

#17289 — Function Prototypes: Necessary or just good practice?

From/dev/phaeton <blahbleh666@no_more_spam.hotmail.com>
Date2012-02-13 23:05 -0600
SubjectFunction Prototypes: Necessary or just good practice?
Message-ID<jhcq3f$sch$1@news.albasani.net>
In K&R2, function definitions in a program were preceded by a function 
prototype, i.e.:

int my_function(int variable1, int variable2);

Then somewhere down the line is the actual definition of the function 
itself:

int my_function(int variable1, int variable2)
	{
	do;
	some;
	stuff;
	return (some_value);
	}


However, I've noticed that if I omit the function prototype, the program 
compiles (with gcc 4.6.x at least) and runs just fine.  Is this 
something that's now acceptable in ANSI standards since K&R2 was 
printed? Or is this 'compiler forgiveness'- letting me do something I 
probably shouldn't?


Thanks.

-J

[toc] | [next] | [standalone]


#17292

FromJohann Klammer <klammerj@NOSPAM.a1.net>
Date2012-02-14 07:31 +0100
Message-ID<4f39ffba$0$18696$91cee783@newsreader03.highway.telekom.at>
In reply to#17289
/dev/phaeton wrote:
> In K&R2, function definitions in a program were preceded by a function
> prototype, i.e.:
>
> int my_function(int variable1, int variable2);
>
> Then somewhere down the line is the actual definition of the function
> itself:
>
> int my_function(int variable1, int variable2)
> {
> do;
> some;
> stuff;
> return (some_value);
> }
>
>
> However, I've noticed that if I omit the function prototype, the program
> compiles (with gcc 4.6.x at least) and runs just fine. Is this something
> that's now acceptable in ANSI standards since K&R2 was printed? Or is
> this 'compiler forgiveness'- letting me do something I probably shouldn't?
>
>
> Thanks.
>
> -J

Hello,

in a sense your function definition includes the prototype..
As long as any function that calls it is further down the file,
there will not be any problems.

methinks the prototype(only) would be

int my_function(int, int);

and the definition(minimum required) would be:

my_function(variable1, variable2)
{

}

if there's no prototype, AFAIK
some assumptions regarding the types
are made by the compiler. It assumes int as return type
and ints for any parameters specified (unless it's pointers
then it is pointers to int).
so for above example you get something like the following:

int my_function(int,int)

which just happens to be your original declaration.

This raises a question..
Why prototypes?
Including type information in function definitions increases
readability and is completely alright for static functions
as long as any functions that call it are further down the file.
However, this usually reverses the 'logical' order of function 
definitions inside a file, so lowest level functions show up
first.
That is why most people explicitly specify prototypes also
for static functions.

They are usually needed for extern functions to be used with
header files, of course.

Warning: above is mostly how I understand C99, I do not know
too much about K&R C. So take it with a grain of salt.

bye,
JK

[toc] | [prev] | [next] | [standalone]


#17305

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2012-02-14 13:14 +0000
Message-ID<0.0a779e9afa88a1fc008c.20120214131443GMT.87aa4l36bg.fsf@bsb.me.uk>
In reply to#17292
Johann Klammer <klammerj@NOSPAM.a1.net> writes:

> /dev/phaeton wrote:
>> In K&R2, function definitions in a program were preceded by a function
>> prototype, i.e.:
>>
>> int my_function(int variable1, int variable2);
>>
>> Then somewhere down the line is the actual definition of the function
>> itself:
>>
>> int my_function(int variable1, int variable2)
>> {
<snip>
>> }
>>
<snip>
> in a sense your function definition includes the prototype..
> As long as any function that calls it is further down the file,
> there will not be any problems.
>
> methinks the prototype(only) would be
>
> int my_function(int, int);

That's fine, but so is the longer form with named parameters given by
the OP.

> and the definition(minimum required) would be:
>
> my_function(variable1, variable2)
> {
>
> }

No, that's not allowed.  First, in C99, you are not allowed to omit the
return type.  Even in older C (where the implicit int return is OK), the
parameters must be declared either in the function declarator (that's
what the OP did and is the modern way) or in a separate declaration list
between the ) and the { like this:

  my_function(variable1, variable2)
  int variable1, variable2;
  {
  }

This last form is old K&R C and was still legal in C90.  Add "int" for
the return type and it's still legal in C99 (though very bad style
nowadays).

> if there's no prototype, AFAIK
> some assumptions regarding the types
> are made by the compiler. It assumes int as return type

In C90 ("ANSI C") yes.  In C99 implicit declarations are not permitted.

> and ints for any parameters specified (unless it's pointers
> then it is pointers to int).
> so for above example you get something like the following:
>
> int my_function(int,int)

No, you get int my_function() and there is a real difference.  You are
confusing what are called the default argument promotions with an
implied prototype.  When there's no prototype, the compiler assumes
nothing about the parameters, but it does perform certain type
conversions in a call.  If the compiler assumed the prototype you've
written, a call like my_function(1.0, 2.0) would have the
arguments converted, but that's not what happens.  The details hardly
matter, since this is only important for very old code.

> which just happens to be your original declaration.
>
> This raises a question..
> Why prototypes?
> Including type information in function definitions increases
> readability and is completely alright for static functions
> as long as any functions that call it are further down the file.

They (prototypes) also cause correct conversion of function arguments.
You don't get that with non-prototype declarations or definitions.

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#17315

FromRalf Damaschke <rwspam@gmx.de>
Date2012-02-14 16:20 +0000
Message-ID<Xns9FF9B0707CC90dammel@y2plugh.fqdn.th-h.de>
In reply to#17305
Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:

> No, that's not allowed.  First, in C99, you are not allowed to
> omit the return type.  Even in older C (where the implicit int
> return is OK), the parameters must be declared either in the
> function declarator (that's what the OP did and is the modern
> way) or in a separate declaration list between the ) and the {
> like this: 
> 
>   my_function(variable1, variable2)
>   int variable1, variable2;
>   {
>   }
> 

I still remember that I used to write
    "main (argc, argv) char **argv; { /* some work */ return 0; }".

And C90 did not break such existing code omitting an implicit int
declaration:

| If the declarator includes an identifier list, the types of the
| parameters may be declared in a following declaration list.  Any
| parameter that is not declared has type int.

-- Ralf

[toc] | [prev] | [next] | [standalone]


#17335

FromPeter Nilsson <airia@acay.com.au>
Date2012-02-14 13:47 -0800
Message-ID<bc49de91-a461-4bf6-9331-77a23bf60e03@vd8g2000pbc.googlegroups.com>
In reply to#17305
Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> In C99 implicit declarations are not permitted.

They're no longer required, but if a C99+ implementation
decides to support them anyway, no diagnostic is required
for their use.

...
> They (prototypes) also cause correct conversion of function
> arguments. ...

Unless the prototype ends with ellipsis and you're back to
default argument promotions for the unnamed arguments.

--
Peter

[toc] | [prev] | [next] | [standalone]


#17336

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-02-14 17:01 -0500
Message-ID<4F3AD9D1.1030207@verizon.net>
In reply to#17335
On 02/14/2012 04:47 PM, Peter Nilsson wrote:
> Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> In C99 implicit declarations are not permitted.
> 
> They're no longer required, but if a C99+ implementation
> decides to support them anyway, no diagnostic is required
> for their use.

Its a constraint violation - 6.7.2p2: "At least one type specifier shall
be given in the declaration specifiers in each declaration,
and in the specifier-qualifier list in each struct declaration and type
name." Therefore a diagnostic is required.

[toc] | [prev] | [next] | [standalone]


#17337

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2012-02-14 22:35 +0000
Message-ID<0.3ce234b7f30119f3e5a4.20120214223533GMT.877gzp11sa.fsf@bsb.me.uk>
In reply to#17336
James Kuyper <jameskuyper@verizon.net> writes:

> On 02/14/2012 04:47 PM, Peter Nilsson wrote:
>> Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>>> In C99 implicit declarations are not permitted.
>> 
>> They're no longer required, but if a C99+ implementation
>> decides to support them anyway, no diagnostic is required
>> for their use.
>
> Its a constraint violation - 6.7.2p2: "At least one type specifier shall
> be given in the declaration specifiers in each declaration,
> and in the specifier-qualifier list in each struct declaration and type
> name." Therefore a diagnostic is required.

I don't think he's talking about implicit int.  I certainly wasn't.

However, I still think it's a constraint violation.  I think 6.5.1 p2
and 6.5.2.2 p1 conspire to make it so (either on it's is probably
enough).

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#17339

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-02-14 17:51 -0500
Message-ID<4F3AE58F.30306@verizon.net>
In reply to#17337
On 02/14/2012 05:35 PM, Ben Bacarisse wrote:
> James Kuyper <jameskuyper@verizon.net> writes:
> 
>> On 02/14/2012 04:47 PM, Peter Nilsson wrote:
>>> Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>>>> In C99 implicit declarations are not permitted.
>>>
>>> They're no longer required, but if a C99+ implementation
>>> decides to support them anyway, no diagnostic is required
>>> for their use.
>>
>> Its a constraint violation - 6.7.2p2: "At least one type specifier shall
>> be given in the declaration specifiers in each declaration,
>> and in the specifier-qualifier list in each struct declaration and type
>> name." Therefore a diagnostic is required.
> 
> I don't think he's talking about implicit int.  I certainly wasn't.

Calling a function without a declaration in scope is a constraint
violation (6.5.2.2p2). If an actual declaration is present, an implied
one is unnecessary (except when the implicit int rule was in effect,
which it no longer is). So if an implicit declaration is needed, there's
either a constraint violation in the declaration of the function or in
the call of the function.

> However, I still think it's a constraint violation.  I think 6.5.1 p2
> and 6.5.2.2 p1 conspire to make it so (either on it's is probably
> enough).

6.5.2.2p1 is the one that seems relevant to me.

[toc] | [prev] | [next] | [standalone]


#17344

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2012-02-15 00:06 +0000
Message-ID<0.01dc16d88541a3158318.20120215000603GMT.871upx0xlg.fsf@bsb.me.uk>
In reply to#17339
James Kuyper <jameskuyper@verizon.net> writes:

> On 02/14/2012 05:35 PM, Ben Bacarisse wrote:
>> James Kuyper <jameskuyper@verizon.net> writes:
>> 
>>> On 02/14/2012 04:47 PM, Peter Nilsson wrote:
>>>> Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>>>>> In C99 implicit declarations are not permitted.
>>>>
>>>> They're no longer required, but if a C99+ implementation
>>>> decides to support them anyway, no diagnostic is required
>>>> for their use.
>>>
>>> Its a constraint violation - 6.7.2p2: "At least one type specifier shall
>>> be given in the declaration specifiers in each declaration,
>>> and in the specifier-qualifier list in each struct declaration and type
>>> name." Therefore a diagnostic is required.
>> 
>> I don't think he's talking about implicit int.  I certainly wasn't.
>
> Calling a function without a declaration in scope is a constraint
> violation (6.5.2.2p2).

Did you mean p2?  p2 is entirely conditional and it might not apply.

> If an actual declaration is present, an implied
> one is unnecessary (except when the implicit int rule was in effect,
> which it no longer is). So if an implicit declaration is needed, there's
> either a constraint violation in the declaration of the function or in
> the call of the function.

I am sure we agree, but I don't find your reasoning easy to follow.  In
addition to text that defines a constraint, there must also be an
absence on any text that permits implicit declarations.  C90 has almost
exactly the same wording as C99's 6.5.2.2 p1 (and p2 for that matter)
yet C99 and C90 differ in this regard.  This is because C90 has wording
(that C99 does not) that defines an explicit declaration in certain
cases.

My point is you can't just say "because of 6.5.2.2p2".  Of course, I
also made this mistake by just citing two sections.  I should also have
said "and there's nothing that says a declaration will be assumed".

>> However, I still think it's a constraint violation.  I think 6.5.1 p2
>> and 6.5.2.2 p1 conspire to make it so (either on it's is probably
>> enough).
>
> 6.5.2.2p1 is the one that seems relevant to me.

I am not sure it has much relevance (see below) but in any case it can't
rule out all cases on it's own.  What's wrong with this:

  void (*fp)(void) = function;

in the absence of a declaration for 'function'?  6.5.2.2 p1 does not
prohibit it, but 6.5.1 p2 does.  As you can see, I'm retracting my view
that either one is probably enough.  I think 6.5.1 p2 is probably enough
on it's own because it says that both the above and

  function();

are constraint violations when there's no function declaration in scope.
6.5.2.2 p1 rules out things like this:

  int f;
  f();

but when f has no declaration at all, f() is not even a function call
expression.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#17351

FromPeter Nilsson <airia@acay.com.au>
Date2012-02-14 20:27 -0800
Message-ID<3d33cbbc-42a2-47f0-a1a2-292b3f96fde8@tj4g2000pbc.googlegroups.com>
In reply to#17336
James Kuyper <jameskuy...@verizon.net> wrote:
> Peter Nilsson wrote:
> > Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> > > In C99 implicit declarations are not permitted.
> >
> > They're no longer required, but if a C99+ implementation
> > decides to support them anyway, no diagnostic is required
> > for their use.
>
> Its a constraint violation - 6.7.2p2: "At least one type specifier shall
> be given in the declaration specifiers in each declaration,
> and in the specifier-qualifier list in each struct declaration and type
> name." Therefore a diagnostic is required.

My bad. I was looking at using functions without a declaration in
scope.
e.g...

  #include <stdio.h>
  int main(void) { foo(); return 0; }
  int foo(void) { puts("42"); return 0; }

AFAICS, if a C99+ implementation supports C90 style implicit function
declarations as an extension, then it is not required to issues a
diagnostic since no constraint would be violated.

--
Peter

[toc] | [prev] | [next] | [standalone]


#17356

FromKeith Thompson <kst-u@mib.org>
Date2012-02-14 22:24 -0800
Message-ID<lny5s4havj.fsf@nuthaus.mib.org>
In reply to#17351
Peter Nilsson <airia@acay.com.au> writes:
[...]
> My bad. I was looking at using functions without a declaration in
> scope.
> e.g...
>
>   #include <stdio.h>
>   int main(void) { foo(); return 0; }
>   int foo(void) { puts("42"); return 0; }
>
> AFAICS, if a C99+ implementation supports C90 style implicit function
> declarations as an extension, then it is not required to issues a
> diagnostic since no constraint would be violated.

No, that's still a constraint violation (strictly speaking a syntax
error), and providing an extension doesn't permit a compiler to
omit the required diagnostic.

C99 6.5.1p2:

    An identifier is a primary expression, provided it has been
    declared as designating an object (in which case it is an lvalue)
    or a function (in which case it is a function designator).

with a footnote:

    Thus, an undeclared identifier is a violation of the syntax.

A conforming C99+ compiler may support this as an extension, but
it still has to issue a diagnostic.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#17295

FromStephen Sprunk <stephen@sprunk.org>
Date2012-02-14 01:18 -0600
Message-ID<jhd1si$sbf$1@dont-email.me>
In reply to#17289
On 13-Feb-12 23:05, /dev/phaeton wrote:
> In K&R2, function definitions in a program were preceded by a function
> prototype, i.e.:
> 
> int my_function(int variable1, int variable2);

Note this is a prototyped function _declaration_.

> Then somewhere down the line is the actual definition of the function
> itself:
> 
> int my_function(int variable1, int variable2)
>     {
>     do;
>     some;
>     stuff;
>     return (some_value);
>     }

This is a prototyped function _definition_.  Note that a definition
declares the function as well, if that hasn't already been done.

> However, I've noticed that if I omit the function prototype,

ITYM the function declaration.

> the program compiles (with gcc 4.6.x at least) and runs just fine.

Since you don't include the rest of the program's source, we don't know
if this is luck or you just didn't happen to do something wrong.

Lots of stuff happens to work "just fine" on some implementations even
though that may not be guaranteed.

> Is this something that's now acceptable in ANSI standards since K&R2
> was printed? Or is this 'compiler forgiveness'- letting me do something I
> probably shouldn't?

It's not new; in fact, it's the old (pre-ANSI) way of doing things.

K&R C allowed calling functions that hadn't previously been declared,
which caused an implicit declaration of a function by that name.  This
was deprecated by ANSI.  Unless you _know_ you are coding for a platform
for which there is no C89 (or later) compiler, which should be
incredibly rare these days, you should always declare your functions.

S

-- 
Stephen Sprunk         "God does not play dice."  --Albert Einstein
CCIE #3723         "God is an inveterate gambler, and He throws the
K5SSS        dice at every possible opportunity." --Stephen Hawking

[toc] | [prev] | [next] | [standalone]


#17296

FromPhilip Lantz <prl@canterey.us>
Date2012-02-14 00:05 -0800
Message-ID<MPG.29a3b5b85c324a5c989684@news.eternal-september.org>
In reply to#17289
/dev/phaeton wrote:
> In K&R2, function definitions in a program were preceded by a function 
> prototype, i.e.:
> 
> int my_function(int variable1, int variable2);
> 
> Then somewhere down the line is the actual definition of the function 
> itself:
> 
> int my_function(int variable1, int variable2)
> 	{
> 	do;
> 	some;
> 	stuff;
> 	return (some_value);
> 	}
> 
> 
> However, I've noticed that if I omit the function prototype, the program 
> compiles (with gcc 4.6.x at least) and runs just fine.  Is this 
> something that's now acceptable in ANSI standards since K&R2 was 
> printed? Or is this 'compiler forgiveness'- letting me do something I 
> probably shouldn't?

1. If all calls to the function are after the definition, then the 
definition acts as a prototype and there is no problem. The following 
points are based on the assumption that there is a call before the 
definition.

2. It's allowed by the C90 standard, as long as the function returns int 
and the correct parameters are passed. The number and types of 
parameters are not checked, and the behavior is undefined if they don't 
match the function definition (based on a non-trivial set of matching 
rules in the standard).

3. It's not allowed by C99 and later standards. Many compilers may still 
support it, though, for backward compatibility.

4. It is letting you do something you probably shouldn't--even when the 
behavior is allowed and defined by the standard, it is much better to 
always have a prototype-style definition or declaration of every 
function before it is called.

[toc] | [prev] | [next] | [standalone]


#17298

FromKaz Kylheku <kaz@kylheku.com>
Date2012-02-14 09:09 +0000
Message-ID<20120214010408.773@kylheku.com>
In reply to#17289
On 2012-02-14, /dev/phaeton <blahbleh666@no_more_spam.hotmail.com> wrote:
> In K&R2, function definitions in a program were preceded by a function 
> prototype, i.e.:

It's good practice to declare functions before calling them.
Calling undeclared functions is a deprecated language feature.

However, there is often no need for prototypes within one translation unit,
because you can organize the code so that each function is defined prior to any
calls to the function. A function definition serves as a prototype declaration.

This arrangement is impossible when you have mutual recursion among
two or more functions. Some of them have to be prototyped.

> However, I've noticed that if I omit the function prototype, the program 
> compiles (with gcc 4.6.x at least) and runs just fine.  

With what warning options?

How about with -Wall and -W?

[toc] | [prev] | [next] | [standalone]


#17354

From/dev/phaeton <blahbleh666@no_more_spam.hotmail.com>
Date2012-02-14 23:51 -0600
Message-ID<jhfh4i$19v$1@news.albasani.net>
In reply to#17298
On 02/14/2012 03:09 AM, Kaz Kylheku wrote:

> With what warning options?
>
> How about with -Wall and -W?

Honestly?  None.  I suppose I should start using them.


However, the gist that I'm getting from all this...

It's a good idea to do prototyping, and in the worst case scenario it is 
just superfluous.  So I will continue to do them.

Sorry to start a lukewarm debate- though it's been quite educational for 
me to read through it.  I thank you all for that.


Stephen Sprunk wrote:

 >> In K&R2, function definitions in a program were preceded by a function
 >> prototype, i.e.:

 >> int my_function(int variable1, int variable2);

 > Note this is a prototyped function _declaration_.

I will have to re-read the K&R2 usage of "definition" and "declaration". 
  I seem to be confused on which is which.  Thanks for the correction.

Out of time for now... Back to A&P II homework for the rest of the 
night.  *sigh*

-J

[toc] | [prev] | [next] | [standalone]


#17357

FromKaz Kylheku <kaz@kylheku.com>
Date2012-02-15 06:36 +0000
Message-ID<20120214222649.979@kylheku.com>
In reply to#17354
On 2012-02-15, /dev/phaeton <blahbleh666@no_more_spam.hotmail.com> wrote:
> On 02/14/2012 03:09 AM, Kaz Kylheku wrote:
>
>> With what warning options?
>>
>> How about with -Wall and -W?
>
> Honestly?  None.  I suppose I should start using them.
>
>
> However, the gist that I'm getting from all this...
>
> It's a good idea to do prototyping, and in the worst case scenario it is 
> just superfluous.  So I will continue to do them.

Or instead of duplicating every declaration, you could just turn on the right
diagnosticxs in the compiler so that you're told when a prototype is necessary,
but missing.

Writing declarations just for the sake of writing declarations can even
lead you to a mistake.

  /* forgot to include "foo.h" where foo is declared */

  int foo(char *x)
  {
  }

If you use -Wstrict-prototypes -Wmissing-prototypes, GCC can help you
catch the problem that a declaration was forgotten.

This could indicate that the header file was not included, meaning
that the program is at risk of being inconsistent (definition changes
but the header file declaration does not).

Sometimes this diagnostic indicates that a function which should be static has
been made external.

But if you have a declaration like in the above, then this diagnostic is shut
up:

  /* forgot to include "foo.h" where foo is declared */

  int foo(char *x);

  /*...*/

  int foo(char *x)
  {
  }

The issue is that "foo.h" could have the wrong prototype, causing other
translation units to have incorrect calls to foo.

[toc] | [prev] | [next] | [standalone]


#17370

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-02-15 08:31 -0500
Message-ID<jhgc40$9oi$1@dont-email.me>
In reply to#17354
On 02/15/2012 12:51 AM, /dev/phaeton wrote:
> On 02/14/2012 03:09 AM, Kaz Kylheku wrote:
> 
>> With what warning options?
>>
>> How about with -Wall and -W?
> 
> Honestly?  None.  I suppose I should start using them.
> 
> 
> However, the gist that I'm getting from all this...
> 
> It's a good idea to do prototyping, and in the worst case scenario it is 
> just superfluous.

Keep in mind that your original question, whatever you might have
thought to the contrary, was not actually about whether prototyping
should be done, but about whether it should be done twice - once in a
function declaration, and a second time in the function definition. The
separate declaration often is, as you say, superfluous, and should not
be used if that is the case.

Whether you need to provide a separate declaration is just a matter of
how you organize your code, but you should always use a prototype
whenever you either declare or define a function. They're extremely
useful - they're never superfluous. That's primarily because they allow
the C implementation to recognize certain common kinds of mistakes, and
require it to give you a diagnostic message if you've made one of those
mistakes.

On the separate declaration issue:
The first part of a function's definition is, in itself, a declaration
of the function, so if you never use a function anywhere but in a single
file, and if you define that function prior to any calls to that
function, a separate declaration of the function unnecessarily
complicates your code, and should not be provided. The only case where
this doesn't work is mutually recursive functions - for instance, if
func1() calls func2(), and func2() also calls func1(), at least one of
them must be declared first, with the definition coming later.

For any function which is used in at least one file other than the one
in which it is defined, you should create a header file containing a
declaration of that function, and #include that header file in any file
where that function is used. You should also #include that header file
in the file where the function is defined - that way, if you made a
mistake and the declaration of the function isn't compatible with the
definition of the function, you'll get a diagnostic message telling you so.
-- 
James Kuyper

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web