Efficient coding considered har

rgh at inmet rgh at inmet
Sun Nov 13 04:28:00 AEST 1988


>another teacher here loves ANSI C, and every 'enhancement' he mentions
>smacks me of being Pascalish in orientation.  For example, the
>declaration of variables within the function parentheses will
>provide the 'protection' that Pascal lovers want only if the
>compiler can compile both the caller and callee at the same time.
>Or the linker must be more sophisticated, using information that
>is generated by the compiler.  How will it be handled folks?
>Either way we lose.  If the compiler does it, there goes our
>modular strategy of putting related functions in seperate files
>from the functions that use them.  But then we could always
>#include C code files, which is exactly what one of the afore-
>mentioned teachers required of beginning C students!  But what
>if I want to package a set of functions for users of equipment
>I manufacture to connect to the computer and I don't want them
>to have the source?  Then the linker will have to do it.  Will
>that cost more for the compiler and linker?

Apparently you've not been informed that function declarations can
use the prototype notation [i.e., declaring argument types as
part of the function header] as well as function definitions.
This addresses all your concerns:  you put a prototype function
declaration in an include file, and include that in all the modules
that call that function, and in the module that defines the function.
The linker doesn't have to do anything special.  You market your
function package as an include file that declares the functions,
along with the object modules that define the functions.
Fairly standard practice these days is to write a .h file declaring
the types, macros, functions that form the external interface of
the corresponding .c file.

There are potential efficiency gains in this prototype business
which should interest you.  In the absence of prototypes, integral
arguments have to be at least int-size, and floating arguments have
to be at least double-size.  That is, an actual argument of type
float is converted to double in the calling sequence.  If the
caller and callee can agree, via prototypes, that the argument
really is a float, then the conversion can be omitted.

More fundamentally, C implementors have had to assume that any function
call might be to a function that takes a variable number of arguments
(such as printf).  This constrains calling sequence design in
various ways.  For instance, several machines have a Return instruction
with a operand specifying how much data to pop off the stack.  You
can't use this instruction unless you know how big the argument
list is, which in classical C you don't.  So generally the argument
list gets popped off the stack at the call site, certainly more
expensive in space and often in time.
Now part of the prototype syntax is specifying functions (like sprintf)
that take optional trailing arguments.  All other functions can
be assumed to take a fixed argument list.  Thus an implementor 
could choose to use that Return-popping-n instruction in most cases.
Passing arguments in registers also becomes a more attractive implementation,
for similar reasons.

Randy Hudson  rgh at inmet.inmet.com   uunet!inmet!rgh



More information about the Comp.lang.c mailing list