[comp.lang.c] Prototypes local or global opinions wanted

draper@buster.cps.msu.edu (Patrick J Draper) (06/21/91)

I'm interested in what others think of the practice of declaring
function prototypes locally within a procedure.


local:

foo ()
{
 int bar (void);
 int x;

   x = bar ();

} 
--------------------------------------------------------------------

global:

int bar (void);

foo ()
{
 int x;

   x = bar ();
}


The advantage to the local declaration that I can see is that an
unintentional call to bar() will be flagged by the compiler. I prefer to
use the global declaration because if the definition of bar should
change, there's one place to change the prototype.

Any other opinions?

Thanks,
------------------------------------------------------------------------
Patrick Draper     "College is supposed to prepare you for the future,
cps.msu.edu               but all my future's behind me." 
draper@cps.msu.edu      -- My GrandPa, age 85, Fall 1990 graduate
                           of Western Michigan University 
------------------------------------------------------------------------

scs@adam.mit.edu (Steve Summit) (06/21/91)

In article <1991Jun20.202241.7531@msuinfo.cl.msu.edu> draper@buster.cps.msu.edu (Patrick J Draper) writes:
>I'm interested in what others think of the practice of declaring
>function prototypes locally within a procedure.
>The advantage to the local declaration that I can see is that an
>unintentional call to bar() will be flagged by the compiler. I prefer to
>use the global declaration because if the definition of bar should
>change, there's one place to change the prototype.
>Any other opinions?

Most certainly.  If prototypes are used, they MUST be placed in
header files (which of course is usually tantamount to "global
placement"), and then #included by all source files in which the
function(s) is called, AND in the source file where the function
is defined.  This way, there's *really* only one place to change
the prototype, and the compiler can check the prototype against
the definition.

If a prototype for an external (i.e. defined in another source
file) function is placed in a source (non-header) file, it's far
too easy to forget to update it if/when the definition changes,
and the prototype then does more harm than if it hadn't been used
at all (it inserts implicit casts and/or generates warnings based
on an obsolete parameter list).

(This assumes you're using multiple source files at all, and is
written from a C perspective.  The use of prototypes is
considerably less optional in C++, and recommended practice for
prototype placement may be different.  My remarks are targeted at
comp.lang.c; note that this article, like the one to which it
responds, is also crossposted to comp.lang.c++ .)

The possibility of an inadvertent call (which might be flagged if
local prototypes were routinely used) is comparatively minor (and
one I've never worried about; I think that local extern data
declarations are a bit silly, too).

                                            Steve Summit
                                            scs@adam.mit.edu

Dave.Harris@f14.n15.z1.fidonet.org (Dave Harris) (06/22/91)

 >The advantage to the local declaration that I can see is that an
 >unintentional call to bar() will be flagged by the compiler. I prefer to
 >use the global declaration because if the definition of bar should
 >change, there's one place to change the prototype.

 >Any other opinions?

Normally that is the best way to do it.  In the gutless wonder world of the 
IBM PC and the crummy compilers such as Microsoft's that run out of memory 
when you include lots of definitions it can help to just prototype what you 
need as opposed to including a whole .h file.  Helps the compile speed to (and 
microsoft needs all the help it can get).

 


 

--  
Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!15!14!Dave.Harris
Internet: Dave.Harris@f14.n15.z1.fidonet.org

mvm@caesun6.harris-atd.com (Matt Mahoney) (06/24/91)

In article <1991Jun20.202241.7531@msuinfo.cl.msu.edu>
  draper@buster.cps.msu.edu (Patrick J Draper) writes:

>I'm interested in what others think of the practice of declaring
>function prototypes locally within a procedure.

Functions are always global, so their prototypes should be global too.

--------------------------------
Matt Mahoney, mvm@epg.harris.com
#include <disclaimer.h>

fxsdb@acad3.alaska.edu (06/25/91)

In article <6592@trantor.harris-atd.com>, mvm@caesun6.harris-atd.com (Matt Mahoney) writes:
> In article <1991Jun20.202241.7531@msuinfo.cl.msu.edu>
>   draper@buster.cps.msu.edu (Patrick J Draper) writes:
> 
>>I'm interested in what others think of the practice of declaring
>>function prototypes locally within a procedure.
> 
> Functions are always global, so their prototypes should be global too.
> 
Functions can be declared locally with local prototypes which was, I believe,
the focus of the question.  I much prefer global functions, as this encourages
writing general functions which are reused throughout the code, and can easily
be #included.
> --------------------------------
> Matt Mahoney, mvm@epg.harris.com
> #include <disclaimer.h>
   -Scott (fxsdb@acad3.alaska.edu)

bhoughto@hopi.intel.com (Blair P. Houghton) (06/25/91)

In article <1991Jun24.132406.1@acad3.alaska.edu> fxsdb@acad3.alaska.edu writes:
>In article <6592@trantor.harris-atd.com>, mvm@caesun6.harris-atd.com
(Matt Mahoney) writes:
>> Functions are always global, so their prototypes should be global too.
>
>Functions can be declared locally with local prototypes which was, I believe,
>the focus of the question.  I much prefer global functions, as this encourages
>writing general functions which are reused throughout the code, and can easily
>be #included.

Block-scoped function definitions can import block-scoped
variables.

Very handy when hacking a decision tree into a former
straight-flow construct.

				--Blair
				  "Information hiding in the rushes."

alanb@sdl.mdcbbs.com (06/25/91)

In article <4845@inews.intel.com>, bhoughto@hopi.intel.com (Blair P. Houghton) writes:
> In article <1991Jun24.132406.1@acad3.alaska.edu> fxsdb@acad3.alaska.edu writes:
>>In article <6592@trantor.harris-atd.com>, mvm@caesun6.harris-atd.com
> (Matt Mahoney) writes:
>>> Functions are always global, so their prototypes should be global too.
>>
>>Functions can be declared locally with local prototypes which was, I believe,
>>the focus of the question.  I much prefer global functions, as this encourages
>>writing general functions which are reused throughout the code, and can easily
>>be #included.
> 
> Block-scoped function definitions can import block-scoped
> variables.
> 
> Very handy when hacking a decision tree into a former
> straight-flow construct.
> 
> 				--Blair
> 				  "Information hiding in the rushes."

But block-scoped function definitions (as opposed to declarations) aren't
available in C (or C++)?
(Thinks - hang on, you're allowed block scope classes with member functions
aren't you - checks manual - local classes have function scope, and can
import only static variables from the enclosing scope - Ellis & Stroustrup 9.8)

Has anyone out there found this useful? Or was this a recommendation to use 
something other than C/C++ to get nested functions?

I agree with the "declare it once only" (in the include file) principle.
C++ type-safe linkage does at least give you a chance of catching incorrect
local declarations though (unless they're extern "C").


alanb@sdl.mdcbbs.com      Alan Braggins      `cat ~/.disclaimer`

phil@phd.UUCP (H Phil Duby) (06/25/91)

In article <1991Jun21.004933.4197@athena.mit.edu> scs@adam.mit.edu (Steve Summit) writes:
> In article <1991Jun20.202241.7531@msuinfo.cl.msu.edu> draper@buster.cps.msu.edu (Patrick J Draper) writes:
> >I'm interested in what others think of the practice of declaring
> >function prototypes locally within a procedure.
> >The advantage to the local declaration that I can see is that an
> >unintentional call to bar() will be flagged by the compiler. I prefer to
> >use the global declaration because if the definition of bar should
> >change, there's one place to change the prototype.
> >Any other opinions?
>
> Most certainly.  If prototypes are used, they MUST be placed in
                                                ^^^^ ???
> header files (which of course is usually tantamount to "global
> placement"), and then #included by all source files in which the
> function(s) is called, AND in the source file where the function
> is defined.  This way, there's *really* only one place to change
> the prototype, and the compiler can check the prototype against
> the definition.
Another alternative that depends both on the intended usage, and
programming style (no flames on that please) coming up :-)

If the function you want to prototype (VERY good idea IMHO) is used by a
set of other functions that can be convienently grouped together into a
single source file, seperate from other functions that should not call the
function, declare the prototype global in that source file, but with the
static qualifier.  Functions in other files will not see the definition,
and calls to the function will generate the same errors as if the function
was only declared locally.

For purists who insist prototypes should also be declared in a header file
that is #included by all source files for a program / system (producing
global definitions), use the (also talked/beaten to death) option of
putting #ifdef #endif pairs around the prototype (with or without the
static qualifier), and provide the appropriate define only in the source
file(s) that SHOULD be calling the function. This can be both the best and
worst option depending on lots of other considerations, mostly to do with
personal preferences / in house standards / conventions / practices / size
of project / ...

I am not promoting any of these as the correct method.  Just pointing out
another USEABLE alternative that can work in some situations.  I don't
think we need another flame war.  Flames to dev.null, or email if you must.

[... normally (IMHO) correct stuff deleted ...]
>                                             Steve Summit
>                                             scs@adam.mit.edu
H. Phil Duby                     uunet!keyword!calgary!ajfcal!mtroyal!phd!phil
(AMiga Users of Calgary)         AMUCexpress BBS - 650 meg PD Software
Fido net node 1:134/27     (403) 282-5137/5171/5224/5238 3/12/24/24 MNP bps

scs@adam.mit.edu (Steve Summit) (06/26/91)

In article <phil.7968@phd.UUCP> phil@phd.UUCP (H Phil Duby) writes:
>In article <1991Jun21.004933.4197@athena.mit.edu> scs@adam.mit.edu (Steve Summit) writes:
>> Most certainly.  If prototypes are used, they MUST be placed in
>> header files...
>
>If the function you want to prototype (VERY good idea IMHO) is used by a
>set of other functions that can be convienently grouped together into a
>single source file, seperate from other functions that should not call the
>function, declare the prototype global in that source file, but with the
>static qualifier.

Phil is quite correct.  I forgot this exception when I made my
blanket statement; a static prototype does belong in the same
source file where the function is defined and used.

>For purists who insist prototypes should also be declared in a header file...
>use the (also talked/beaten to death) option of
>putting #ifdef #endif pairs around the prototype (with or without the
>static qualifier), and provide the appropriate define only in the source
>file(s) that SHOULD be calling the function.

I hope Phil didn't get the impression I was that kind of a purist --
blindly putting static prototypes in header files just because of
some silly rule would be, well, silly.

Using private #ifdefs in public header files is mildly ugly, and
should only be resorted to when the private declarations must be
shared by a group of "private" files which for some reason cannot
be combined into one file, such that the static storage-class
cannot be used.

(Note, by the way, that a header-file declaration for a static
object or function, if such a declaration is used at all, should
also have the static storage-class, because the ANSI standard
says that the first declaration seen must agree with the
definition with respect to the presence or absence of the static
storage-class.  This is another old and tired topic, which I am
not suggesting that we reopen.)

                                            Steve Summit
                                            scs@adam.mit.edu

mouse@thunder.mcrcim.mcgill.edu (der Mouse) (06/28/91)

In article <4845@inews.intel.com>, bhoughto@hopi.intel.com (Blair P. Houghton) writes:
> In article <1991Jun24.132406.1@acad3.alaska.edu> fxsdb@acad3.alaska.edu writes:
>> In article <6592@trantor.harris-atd.com>, mvm@caesun6.harris-atd.com (Matt Mahoney) writes:
>>> Functions are always global, so their prototypes should be global too.
>> Functions can be declared locally with local prototypes [...]
> Block-scoped function definitions can import block-scoped variables.

Are you aware you're cross-posting to comp.lang.c as well as .c++?

(Block-scoped functions don't exist in C.)

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu