Static function prototype

W

Why Tea

I seem to remember that in ANSI C, all static functions should have
their function prototypes listed at the beginning of the file for
better consistency (or something like that). I googled and didn't find
any good explanation about it. Could the experts please give me an
explanation or point me to some link? Thanks!

/Why Tea
 
D

danmath06

I seem to remember that in ANSI C, all static functions should have
their function prototypes listed at the beginning of the file for
better consistency (or something like that). I googled and didn't find
any good explanation about it. Could the experts please give me an
explanation or point me to some link? Thanks!

/Why Tea

In a file each function can only see the ones declared above it.
That's why it's good practice to have all the prototypes at the top of
the file. The functions that have not been declared before you invoke
them will be asumed to return int and as far as I know the arguments
will not be checked because there is no definition to check them
against to. This applies to all functions static or not.
 
F

Fred

     Stepping back a little, it's always been good practice to
declare functions, static or otherwise, before using them.  (C99
makes this not just good practice, but a requirement.)  And ever
since ANSI C appeared, it's been good practice to use prototypes
in function declarations and definitions.  So the advice about
declaring functions applies to all functions, not just to static
functions.

     Now to matters of layout, which is what your question really
boils down to.  Non-static functions in "serious" programs should
usually be declared by including the associated headers, so all
you see in the .c source file is usually a few #include directives.
Static functions should almost never be declared in headers: You
made them static because you wanted their names to be visible only
inside one module, so why would you export those names to other
modules?  Thus, static functions are usually declared differently
from external functions -- the declarations themselves look the
same, apart from `static', but their placement is different.

     Two principal styles of arranging functions within a module
are commonly seen.  One puts the top-level functions -- main(),
for example -- early in the file, with subordinate functions later
and low-level "leaf" functions last of all.  In this style the
function's definition usually appears after at least one of its
calls, perhaps after all of them, so good practice (or C99's
mandate) calls for putting a separate declaration somewhere prior
to the first use.  The top of the file is a pretty good location.

     Some people (I'm one of them) dislike telling the compiler the
same thing twice; it irks us to declare that foo() takes two int
arguments and returns a double, and then turn right around and
write the actual definition of foo() with two int arguments and a
double result.  When we get irked enough, we sometimes take advantage
of the fact that a function's definition can also serve as its
declaration: If the definition appears before the function's first
use, no separate declaration is needed.  So we write the module
"upside-down" or "Pascal-style:" low-level "leaf" functions at the
top, followed by intermediate-level functions, and the Big Kahuna
last of all, each function declared by its own definition.

     If you've got two or more mutually recursive functions -- f()
calls g() *and* g() calls f() -- you won't be able to use the
definitions-are-declarations strategy for all of them.  If f()
appears first, its call to g() appears before the definition of g()
and you'll need to insert a separate declaration of g() somewhere
before f() in the file.

Many other styles. I prefer main() to be the first (if there is a main
- the module might be a library), followed by the rest, in
alphabetical order. That allows one to easily find the function body
(especially if it is called from many other functions).
 
W

Why Tea

     Stepping back a little, it's always been good practice to
declare functions, static or otherwise, before using them.  (C99
makes this not just good practice, but a requirement.)  And ever
since ANSI C appeared, it's been good practice to use prototypes
in function declarations and definitions.  So the advice about
declaring functions applies to all functions, not just to static
functions.

     Now to matters of layout, which is what your question really
boils down to.  Non-static functions in "serious" programs should
usually be declared by including the associated headers, so all
you see in the .c source file is usually a few #include directives.
Static functions should almost never be declared in headers: You
made them static because you wanted their names to be visible only
inside one module, so why would you export those names to other
modules?  Thus, static functions are usually declared differently
from external functions -- the declarations themselves look the
same, apart from `static', but their placement is different.

     Two principal styles of arranging functions within a module
are commonly seen.  One puts the top-level functions -- main(),
for example -- early in the file, with subordinate functions later
and low-level "leaf" functions last of all.  In this style the
function's definition usually appears after at least one of its
calls, perhaps after all of them, so good practice (or C99's
mandate) calls for putting a separate declaration somewhere prior
to the first use.  The top of the file is a pretty good location.

     Some people (I'm one of them) dislike telling the compiler the
same thing twice; it irks us to declare that foo() takes two int
arguments and returns a double, and then turn right around and
write the actual definition of foo() with two int arguments and a
double result.  When we get irked enough, we sometimes take advantage
of the fact that a function's definition can also serve as its
declaration: If the definition appears before the function's first
use, no separate declaration is needed.  So we write the module
"upside-down" or "Pascal-style:" low-level "leaf" functions at the
top, followed by intermediate-level functions, and the Big Kahuna
last of all, each function declared by its own definition.

     If you've got two or more mutually recursive functions -- f()
calls g() *and* g() calls f() -- you won't be able to use the
definitions-are-declarations strategy for all of them.  If f()
appears first, its call to g() appears before the definition of g()
and you'll need to insert a separate declaration of g() somewhere
before f() in the file.

Thanks Eric for such a clear explanation. While I get your attention,
can we take a look at "extern" as well? :) If we have all exported
functions and global variables included in a header file, does
it mean that there is really no need to use extern (in the module
that needs to access those functions and global variables) as we
can simply #include the header file? What are the needs/advantages
of using extern?

/Why Tea
 
A

Antoninus Twink

I prefer main() to be the first (if there is a main - the module might
be a library), followed by the rest, in alphabetical order. That
allows one to easily find the function body (especially if it is
called from many other functions).

Have you considered using a more sophisticated editor than MS NotePad?
 
B

Ben Bacarisse

Fred said:
On Oct 3, 10:59 am, Eric Sosman <[email protected]> wrote:
... write the module
Many other styles. I prefer main() to be the first (if there is a main
- the module might be a library), followed by the rest, in
alphabetical order. That allows one to easily find the function body
(especially if it is called from many other functions).

That's a new one! I like to tell a story with the code. Sometimes
you introduce the characters first and show how they interact.
Sometimes you give away the whole plot up front like an opera
programme, and sometimes you do a bit of both. But I would prefer to
be free to tell the story without a constraint like yours that seems
to be come from having poor tools.
 
S

s0suk3

On Oct 3, 11:59 am, Eric Sosman <[email protected]> wrote:
Thanks Eric for such a clear explanation. While I get your attention,
can we take a look at "extern" as well? :) If we have all exported
functions and global variables included in a header file, does
it mean that there is really no need to use extern (in the module
that needs to access those functions and global variables) as we
can simply #include the header file? What are the needs/advantages
of using extern?

None. The 'extern' storage class in the declaration/definition of a
function serves no purpose whatsoever. 'extern' suggests that the
function has external linkage, but that is the default for functions
anyway. In other words, declaring/defining a function to be 'extern'
is like defining a local variable to be 'auto'.

Sebastian
 
C

CBFalconer

Why said:
I seem to remember that in ANSI C, all static functions should
have their function prototypes listed at the beginning of the
file for better consistency (or something like that). I googled
and didn't find any good explanation about it. Could the experts
please give me an explanation or point me to some link? Thanks!

Nonsense. Functions should be defined before use. Simply
describing the function in its source provides that. So all you
have to do is put things in a sane order.

Things are different when you are linking to code in another source
module. In that case you have a collection of definitions (in a .h
file) that defines the routines you want visible externally.
Possibly also the types and global variable. Then including that
header file in both sources does the trick.
 
K

Keith Thompson

CBFalconer said:
Nonsense. Functions should be defined before use. Simply
describing the function in its source provides that. So all you
have to do is put things in a sane order.
[...]

Do you mean "declared", rather than "defined"? If you have mutual
recursion, it's not possible for every function to be defined before
use.

Putting prototypes for all static functions at the top of a source
file (after any #include directives) is not required, but it's not an
unreasonable practice.
 
C

CBFalconer

Keith said:
CBFalconer said:
Nonsense. Functions should be defined before use. Simply
describing the function in its source provides that. So all you
have to do is put things in a sane order.
[...]

Do you mean "declared", rather than "defined"? If you have mutual
recursion, it's not possible for every function to be defined
before use.

Putting prototypes for all static functions at the top of a source
file (after any #include directives) is not required, but it's not
an unreasonable practice.

I invariably foul up the usage of 'declared' versus 'defined'. At
least I know what I mean. :)

My practice is to declare everything before use, if possible.
Obviously mutual recursion alters this. But that avoids ever
needing to maintain two source chunks to have the identical
meaning.
 
B

Ben Bacarisse

CBFalconer said:
Keith said:
CBFalconer said:
Why Tea wrote:

I seem to remember that in ANSI C, all static functions should
have their function prototypes listed at the beginning of the
file for better consistency (or something like that). I googled
and didn't find any good explanation about it. Could the experts
please give me an explanation or point me to some link? Thanks!

Nonsense. Functions should be defined before use. Simply
describing the function in its source provides that. So all you
have to do is put things in a sane order.
[...]

Do you mean "declared", rather than "defined"? If you have mutual
recursion, it's not possible for every function to be defined
before use.

Putting prototypes for all static functions at the top of a source
file (after any #include directives) is not required, but it's not
an unreasonable practice.

I invariably foul up the usage of 'declared' versus 'defined'. At
least I know what I mean. :)

My practice is to declare everything before use, if possible.
Obviously mutual recursion alters this.

How? Have you confused them again? I assumed that you got the
meaning right the first time. I.e. that you were advocating a classic
Pascal style in C.
But that avoids ever
needing to maintain two source chunks to have the id entical
meaning.

This, to me, confirms that you are advocating definition before use.
 
C

CBFalconer

Malcolm said:
For a long time I did all my programming from the Visual Studio
GUI. You get into the way of working with it. It's a very
intimate thing, a bit like driving a car.
.... snip ...

--
+-------------------+ .:\:\:/:/:.
| PLEASE DO NOT F :.:\:\:/:/:.:
| FEED THE TROLLS | :=.' - - '.=:
| | '=(\ 9 9 /)='
| Thank you, | ( (_) )
| Management | /`-vvv-'\
+-------------------+ / \
| | @@@ / /|,,,,,|\ \
| | @@@ /_// /^\ \\_\
@x@@x@ | | |/ WW( ( ) )WW
\||||/ | | \| __\,,\ /,,/__
\||/ | | | jgs (______Y______)
/\/\/\/\/\/\/\/\//\/\\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
==============================================================

fix (vb.): 1. to paper over, obscure, hide from public view; 2.
to work around, in a way that produces unintended consequences
that are worse than the original problem. Usage: "Windows ME
fixes many of the shortcomings of Windows 98 SE". - Hutchinson
 
G

Giorgos Keramidas

For a long time I did all my programming from the Visual Studio
GUI. You get into the way of working with it. It's a very intimate
thing, a bit like driving a car.

Then times change, a Beowulf cluster appears, and suddenly that
delightful GUI is taken away. It's actually better to get into the
habit of typing things into simple ASCII editors and using printf() as
your debugger. Now I use emacs. it is a tremendously powerful editor,
but I am quite incapable of doing anything clever with it. I close it
down and use grep when I need to search for a function.

This is off-topic for comp.lang.c, so I've set the `Followup-To' header
appropriately.

Emacs is, indeed, a powerful editing application. It may be interesting
for your editing sessions to read the following pages of the Emacs Wiki:

http://www.emacswiki.org/cgi-bin/wiki/GrepMode
http://www.emacswiki.org/cgi-bin/wiki/RecursiveGrep

The Emacs manual describes various ways of launching grep-like searches
from within Emacs too. See the section ``Searching with Grep under
Emacs'' in the manual.

In recent Emacs releases (i.e. 22.1 or later) you can open this section
by typing

C-h r i grep RET

The `C-h r' keys will launch the Emacs manual in Info mode, and the rest
of the key sequence (the `i grep RET' keys) will open the grep section
by looking up the term `grep' in the index of the manual.

Please feel free to ask about other useful things you want to do with
your Emacs installations, by posting email questions to

(e-mail address removed)

or by posting your questions through Usenet to the `group.

Have fun with your Emacs installations,
Giorgos
 
N

Nick Keighley

I invariably foul up the usage of 'declared' versus 'defined'.  At
least I know what I mean. :)

me too. In fact I'm half convinced that Cs usage is the opposite
of some other language I used (pascal?). This is why I the definition
of definition written on the wall. I check my wall everytime
I post about definion or declaration.

My practice is to declare everything before use, if possible.

yes. Old pascal habbit.
Obviously mutual recursion alters this.  But that avoids ever
needing to maintain two source chunks to have the identical
meaning.

The code equivalent of Normal Form.
 
B

Ben Pfaff

CBFalconer said:
I maintain that ex-ISO-Pascalers write better organized code. :)

Like this?
while ((EOF != (ch = getchar()))} && isspace(ch)) continue;
Ugh. It even has a stray }.
 
A

Antoninus Twink

Like this?
while ((EOF != (ch = getchar()))} && isspace(ch)) continue;
Ugh. It even has a stray }.

Yup - CBF's train-wreck style of coding is an affront to taste and
decency.

Hopefully there won't be any impressionable newbies who follow his
example and create hard-to-read, hard-to-debug monstrosities like the
line above.
 
G

Giorgos Keramidas

Yup - CBF's train-wreck style of coding is an affront to taste and
decency.

Hopefully there won't be any impressionable newbies who follow his
example and create hard-to-read, hard-to-debug monstrosities like the
line above.

Nothing that can't be solved with a GNU indent(1) run here, though. So
move along, move along...
 
C

CBFalconer

Ben said:
Like this?
while ((EOF != (ch = getchar()))} && isspace(ch)) continue;
Ugh. It even has a stray }.

That's a mistyped ')'. The statement itself isn't allowed in
Pascal, because assignments can't be propagated in expressions.
Also eof is a condition, not a macro value.
 
B

Ben Pfaff

CBFalconer said:
That's a mistyped ')'. The statement itself isn't allowed in
Pascal, because assignments can't be propagated in expressions.
Also eof is a condition, not a macro value.

Um, that's your own code, from article <[email protected]>.
 

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,774
Messages
2,569,599
Members
45,170
Latest member
Andrew1609
Top