Function declarations - why are they needed?

S

Seeker

I have a question about the design of C. Why do we have to declare
functions? It's inevitable that once a function is called the
compiler will need to know its definition to branch to it, so with
the definition it'll know the return type and the argument types. Why
do we need to declare functions in every source file we need them?

For example in Python functions are defined once and never declared
anywhere.
 
I

Ian Collins

Seeker said:
I have a question about the design of C. Why do we have to declare
functions? It's inevitable that once a function is called the
compiler will need to know its definition to branch to it, so with
the definition it'll know the return type and the argument types. Why
do we need to declare functions in every source file we need them?
We don't, provided they are defined before they are used.
For example in Python functions are defined once and never declared
anywhere.

Python is an interpreted language where the interpreter can see all the
function definitions (or find them) at run time. C is a compiled
language where components can be built (compiled) in isolation, so
functions that are defined elsewhere have to be declared.
 
F

Frederick Gotham

Seeker posted:
I have a question about the design of C. Why do we have to declare
functions? It's inevitable that once a function is called the
compiler will need to know its definition to branch to it, so with
the definition it'll know the return type and the argument types. Why
do we need to declare functions in every source file we need them?

For example in Python functions are defined once and never declared
anywhere.


A compiler reads a source file just like a human would, line by line, left
to right, top to bottom. So if it reads the following source file:

void Func(void)
{
int j = 7;

j += OtherFunc(); /* THIS LINE */
}


int OtherFunc(void)
{
return 3;
}

It will get as far as THIS LINE and say "What is OtherFunc? Never heard of
it!".

Therefore you introduce it to the compiler by providing a declaration:

int OtherFunc(void);

void Func(void)
{
int j = 7;

j += OtherFunc();
}

int OtherFunc(void)
{
return 3;
}

Because we can declare things before defining things, it's possible to have
two things to refer to each other. Consider two functions that call each
other:

int Func2(int const);

int Func1(int const i)
{
if (7 == i) return Func2(i);

return i - 3;
}


int Func2(int const i)
{
return Func1(i + 9);
}
 
A

Ancient_Hacker

Seeker said:
I have a question about the design of C. Why do we have to declare
functions?


Several reasons.
It's inevitable that once a function is called the
compiler will need to know its definition to branch to it,

Not quite. Most C compilers can emit code with external references,
which are
found by a separate linker program. So when you call foo(), the
compiler puts out literally into the .obj file opcode(call),"foo".
The compiler has no idea where foo is, source or object code.
so with
the definition it'll know the return type and the argument types.

As mentioned before, the foo() source and object files may not even
exist at this time.
The compiler sure can use some hint as to the parameters and return
types, other wise it won't know whether to push the parameter values,
or addresses (in case of a C++ by-ref parameter), and it won't know
what to do with the returned value.
 
J

Jiri Slaby

Seeker napsal(a):
I have a question about the design of C. Why do we have to declare
functions? It's inevitable that once a function is called the
compiler will need to know its definition to branch to it, so with
the definition it'll know the return type and the argument types. Why
do we need to declare functions in every source file we need them?

Every .c file may be (and mostly is) compiled standalone. Glimph phase needs to
know prototype every time the function is called to check types and optimize.
 
J

Joe Wright

Seeker said:
I have a question about the design of C. Why do we have to declare
functions? It's inevitable that once a function is called the
compiler will need to know its definition to branch to it, so with
the definition it'll know the return type and the argument types. Why
do we need to declare functions in every source file we need them?

For example in Python functions are defined once and never declared
anywhere.

If the function you are calling is not in the current translation unit,
the compiler has no idea how it is defined. That's why you want to
prototype it in the current translation unit.
 
M

Mark McIntyre

I have a question about the design of C. Why do we have to declare
functions? It's inevitable that once a function is called the
compiler will need to know its definition to branch to it,

And so it needs to find a definition.

One method, used by some languages, is to read every single file once
to get function definitions, and then a second time to compile it.
This can be exceptionally inefficient with large projects containing
many files and many MLOC.
For example in Python functions are defined once and never declared
anywhere.

Python typically isn't used for large MLOC programmes so the
performance penalty is small.



--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
M

Mark McIntyre

Python is an interpreted language

Is it? Curious, I seem to have a load of compiled python modules on my
C drive !
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
 
R

Robert Gamble

Mark said:
Is it? Curious, I seem to have a load of compiled python modules on my
C drive !

<OT>
As a load-time optimization python can store pre-compiled byte-code
versions of scripts so that they do not need to be interpreted again
the next time the program is run. The platform-independent byte-code
produced still needs to be executed by the Python runtime and is still
the result of an initial run through the interpreter. You can argue
the semantic details of what comprises a "compiled language" and a
"interpreted language" and it is true that any interpreted language can
theoretically be compiled into machine code and vice versa, but in
general Python is considered an interpreted language as is Perl, Ruby,
etc.
</OT>

Robert Gamble
 
J

Julian V. Noble

Seeker said:
I have a question about the design of C. Why do we have to declare
functions? It's inevitable that once a function is called the
compiler will need to know its definition to branch to it, so with
the definition it'll know the return type and the argument types. Why
do we need to declare functions in every source file we need them?

For example in Python functions are defined once and never declared
anywhere.

Same is true for Fortran. Functions are declared in C to ease the
job of writing the compiler. If the function is declared at the
beginning the compiler doesn't have to search through the entire
program to resolve forward references. Of course this could have
been handled by not treating an unresolved compile-time forward
reference as an error, but then the error handling would be differ-
ent. IIRC M$ QuickBasic also required function declarations in the
preamble of the program. It's a design choice.
 
B

Barry Schwarz

I have a question about the design of C. Why do we have to declare
functions? It's inevitable that once a function is called the
compiler will need to know its definition to branch to it, so with
the definition it'll know the return type and the argument types. Why
do we need to declare functions in every source file we need them?
Do you always call printf or sscanf with the same number and type of
arguments? Do you ever use a function that returns an integer type in
a floating point expression? Do you ever use strtol to assign a value
to an int?


Remove del for email
 
J

Joe Wright

Julian said:
Same is true for Fortran. Functions are declared in C to ease the
job of writing the compiler. If the function is declared at the
beginning the compiler doesn't have to search through the entire
program to resolve forward references. Of course this could have
been handled by not treating an unresolved compile-time forward
reference as an error, but then the error handling would be differ-
ent. IIRC M$ QuickBasic also required function declarations in the
preamble of the program. It's a design choice.
The ease of writing a compiler has nothing to do with it. It is the
speed (efficiency?) of compiling and linking to an executable. The C
model is essentially single-pass and forward references cannot be
supported.

You know that, right?
 
D

Dik T. Winter

> On Sat, 8 Jul 2006 11:31:37 +0000 (UTC), in comp.lang.c , Seeker

>
> Python typically isn't used for large MLOC programmes so the
> performance penalty is small.

This is, eh, wrong. The same holds in Fortran where you need not declare
functions anywhere, or only the return type when it is not the default.
Fortran is typically used for large MLOC programs and there is *no*
performance penalty.

The reason is that giving declarations gives the compiler the option to
check parameter types and act accordingly when they do not match the
types of the actual parameters supplied. In Python all types of
parameters are passed the same way to a function, including type
information.
 
D

Dik T. Winter

>
> Same is true for Fortran. Functions are declared in C to ease the
> job of writing the compiler. If the function is declared at the
> beginning the compiler doesn't have to search through the entire
> program to resolve forward references.

Also wrong. Before C89 function declarations did not even exist (or
did barely exist, only in the same way as in Fortran, to determine the
return type if it was non-standard). The only reason for them is to
early find parameter type mismatches. Forward references can be handled
the same way as external references. No problem for the compiler.
 
D

Dik T. Winter

> The ease of writing a compiler has nothing to do with it. It is the
> speed (efficiency?) of compiling and linking to an executable. The C
> model is essentially single-pass and forward references cannot be
> supported.
>
> You know that, right?

I did not know that. The very first Pascal compiler I ever used (the
compiler for the original Pascal written by Urs Amman at the ETH in
Zuerich), was single pass and allowed forward references. It was the
linking loader that resolved the forward references.
 
J

Joe Wright

Dik said:
I did not know that. The very first Pascal compiler I ever used (the
compiler for the original Pascal written by Urs Amman at the ETH in
Zuerich), was single pass and allowed forward references. It was the
linking loader that resolved the forward references.

I keep promising myself to be more careful in my posts here. Of course,
the compiler and linker, together can resolve forward and external
references to objects and functions rather well.

My apologies.
 
D

Dave Thompson

This is, eh, wrong. The same holds in Fortran where you need not declare
functions anywhere, or only the return type when it is not the default.
Fortran is typically used for large MLOC programs and there is *no*
performance penalty.
In classic FORTRAN, or the (nearly) equivalent subset of modern
Fortran. Where, as you note below, all arguments to all routines are
passed the same way -- usually, and canonically, all by reference,
although value-return was also permitted and sometimes used at least
for certain types like scalar integers and floats.

Except if you use the same name as an 'instrinsic' (= builtin =
standard) routine, in which case you need to declare it EXTERNAL even
if you don't (need to) declare the type.
The reason is that giving declarations gives the compiler the option to
check parameter types and act accordingly when they do not match the
types of the actual parameters supplied. In Python all types of
parameters are passed the same way to a function, including type
information.

In modern Fortran (>=90) there are new options for parameters (which
Fortran calls dummy arguments, using the term parameter for something
else) which require the called routine to have an 'explicit interface'
visible to the caller. This is semantically equivalent to a prototype
in C (or declaration in C++), but a bit confusingly is not always
actually written. There are three choices:

- Fortran (now) allows 'contained' = nested (to one level) routines.
Such a contained routine necessarily appears in the same source unit
(after preprocessing if applicable) as the caller and its 'explicit'
interface is (implicitly!) available.

- Similarly it provides 'modules' similar to Java or Ada packages,
which can store data and (selectively) export routines (and data
items) to client code. Such a module is separately compiled and
produces, in addition to object code for linking and execution,
interface info, typically in an x.mod file, used to compile clients.

- Finally, for separately compiled (including third-party) code to
which neither of these applies, you write an actual description called
an interface block, similar to an actual Fortran subprogram header and
not too unlike a K&R1C function definition header.

- David.Thompson1 at worldnet.att.net
 

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

No members online now.

Forum statistics

Threads
474,184
Messages
2,570,978
Members
47,561
Latest member
gjsign

Latest Threads

Top