What's it with this kind of definition?

C

Curious Student

Some places till now, I've seen function prototypes within functions
instead of in the global declaration space, which I thought was the
way.

I thought it was <I>only</I>:

int myfunction(int, int);

int main(void)
{
int a,b;
return myfunction(a,b);
}

But I've also seen:

int main(void)
{
int a, b, myfunction(int, int);
return myfunction(a,b);
}
I've seen this in K&R as well, but haven't come accross a piece that
talks about this kinda declaration.
What's the deal here? I understand it as follows:

It defines the scope of usage. If defined in the global space, much
like extern variables, the function can be called from anywhere within
the file. If declared within another function, it may be called only
from within that function in which it is defined.

How true?
 
C

Christian Bau

Some places till now, I've seen function prototypes within functions
instead of in the global declaration space, which I thought was the
way.

I thought it was <I>only</I>:

int myfunction(int, int);

int main(void)
{
int a,b;
return myfunction(a,b);
}

But I've also seen:

int main(void)
{
int a, b, myfunction(int, int);
return myfunction(a,b);
}
I've seen this in K&R as well, but haven't come accross a piece that
talks about this kinda declaration.
What's the deal here? I understand it as follows:

It defines the scope of usage. If defined in the global space, much
like extern variables, the function can be called from anywhere within
the file. If declared within another function, it may be called only
from within that function in which it is defined.

How true?

That is probably correct. However, it is an extremely bad programming
style. Here is why:

You write functions that are called only from within the file containing
them (to be more precise: From the same compilation unit), and functions
that are called from other places as well. For the first type, you
should use static functions. For the second type, you use extern
functions.

Every caller needs to know how to call a function. Since for extern
functions the caller usually cannot see the definition of the function,
you write a function declaration and put it into a header file, and
every caller should include that header file. You might change the
function parameters at some point in the future; in that case you also
change the declaration in the header file. If the new declaration is not
compatible with the old one, then the compiler will refuse to compile
callers of the function that have not been adapted to the new
parameters.

In the example you wrote, the declaration of myfunction is within main.
If someone changes the definition of myfunction, and also changes the
declaration in the header file, there is a good chance that the
declaration in main is missed. I could have changed it to "myfunction
(double, double, double)", but the compiler would still assume that
myfunction takes two int arguments, so it will not tell you that the
call to myfunction is incorrect, and things will go badly wrong.

You should never have the declaration of a function anywhere but in
exactly _one_ header file.
 
C

CBFalconer

Christian said:
.... snip ...

You should never have the declaration of a function anywhere but
in exactly _one_ header file.

Never say never :) What about mutual recursion, e.g.:

static void foo(int bar);

static void fuzz(int ball)
{
printf("fuzz (%d}\n", ball);
if (ball) foo(ball - 1);
}

static void foo(int bar)
{
printf("foo (%d}\n", bar);
if (bar) fuzz(bar - 1);
}
.....
foo(12);
.....
 
R

Richard Bos

CBFalconer said:
Never say never :) What about mutual recursion, e.g.:

static void foo(int bar);

static void fuzz(int ball)
{
printf("fuzz (%d}\n", ball);
if (ball) foo(ball - 1);
}

Not just mutual recursion. I never put any declarations of static
functions in a header; they all go at the top of their own source file.
Nobody else needs to know their declarations; functions in that one
source file do.

Richard
 
C

CBFalconer

Richard said:
Not just mutual recursion. I never put any declarations of static
functions in a header; they all go at the top of their own source
file. Nobody else needs to know their declarations; functions in
that one source file do.

That case never arises for me, because I always define functions
before use. Main comes last.
 
R

Richard Bos

CBFalconer said:
That case never arises for me, because I always define functions
before use. Main comes last.

Clearly a case where tastes differ, since I do it exactly the other way
'round. I rarely design top-down, but I do prefer to be able to read my
code in that order.

Richard
 
C

CBFalconer

Richard said:
Clearly a case where tastes differ, since I do it exactly the
other way 'round. I rarely design top-down, but I do prefer to
be able to read my code in that order.

Hah! And I virtually always design top-down. I also always bottom
post.
 
E

E. Robert Tisdale

Curious said:
Some places till now, I've seen function prototypes within functions
instead of in the global declaration space,
which I thought was the way.

I thought it was <I>only</I>:

int myfunction(int, int);

int main(int argc, char* argv[]) {
int a, b;
return myfunction(a, b); return 0;
}

But I've also seen:

int main(int argc, char* argv[]) {
int a, b, myfunction(int, int);
return myfunction(a,b); return 0;
}
I've seen this in K&R as well, but haven't come across a piece
that talks about this kind of declaration.
What's the deal here? I understand it as follows:

It defines the scope of usage. If defined in the global space, much
like extern variables, the function can be called from anywhere within
the file. If declared within another function, it may be called only
from within that function in which it is defined.

How true?

Suppose that you are writing a "wrapper" for a Fortran function:

double force(double mass, double acceleration) {
extern double force_(const double*, const double*);
return force_(&mass, &acceleration);
}

The idea is that you want C programmers to use function

force(double, double)

instead of function

force_(const double*, const double*)

so the only place that you declare force_(const double*, const double*)
is in force(double, double).
The Fortran function prototype isn't available to programmers.
This doesn't prevent C programmers from calling the Fortran function --
it just makes it a little more difficult and, maybe,
they will get the idea that they shouldn't call it directly.
 
D

Dan Pop

In said:
Hah! And I virtually always design top-down. I also always bottom
post.

I design top-down and implement bottom-up. This allows testing each
function as soon as it is written, which minimizes the debugging/testing
of the application (it's much easier to test the correctness of each
function independently of the rest of the application) so debugging the
application boils down to removing the bugs from the main function.

Then again, in a previous life, I was writing embedded control
applications, in assembly, without the benefit of an ICE (in-circuit
emulator) and my *only* debugging tool was an oscilloscope. Much easier
to avoid introducing bugs in the first place than to find them afterwards.

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
474,143
Messages
2,570,822
Members
47,368
Latest member
michaelsmithh

Latest Threads

Top