lint (was: Funny mistake)

D'Arcy J.M. Cain darcy at druid.uucp
Mon Mar 25 02:57:19 AEST 1991


In article <1991Mar23.043408.5260 at athena.mit.edu> scs at adam.mit.edu writes:
>In article <13627 at helios.TAMU.EDU> byron at archone.tamu.edu (Byron Rakitzis) writes:
>I don't believe that ANSI C prototypes, as currently defined and
>commonly implemented, are a sufficient solution to the problem of
>cross-file declaration mismatches.

As with anything the tool by itself is never a sufficient solution.  Lint
and prototypes both require intelligent use to get the most from them.  I
believe that prototypes used properly can enhance the development process.

There is a commercial for Pert shampoo (is there such a thing as realpoo?)
that shows a woman holding a bottle and easily moving around a locker room
while someone in the background who supposedly is using the old style two
bottle system that can barely stumble to the shower she is so overloaded with
bottles, towels, etc.  Somehow that one extra bottle of conditioner translates
into an armful of stuff.  Your post reminds me of that somewhat.  Sure there
is some more work required to work with prototypes but it isn't nearly so
bad as you make it seem and I think the benefits really make it worhwhile
in the long run.  I have been using full prototypes for years and it has
saved my bacon too many times to even consider going to some other system.

First of all, the standard headers will take care of most of your checking.
If you use a standard I/O function, #include stdio.h.  If you are using
any time functions then #include time.h.  If you turn on enough warnings
the compiler will remind you if you forget a header by pointing out that
a function hasn't been prototyped.

If you have a number of functions that are shared in a project, create
a header file or a few headers where the functions are declared.  Make
sure to include the header in the file that defines the function.  This
is a check on the header file as well as the function.  The header file
can perform double duty if you wish by documenting the project as well
as specifying the interfaces to the various routines.  I have one header
file that runs to ~16 pages with ~90% devoted to comments.  It is in
effect the functional specification for the sub-system it describes.
Now if a change is made to the specification the sub-system as well as
those programs that use it are automatically checked.  As for the header
file, consider the following:

    /* The foo function performs a framitz function on the string that */
    /* is sent as the first argument and returns a pointer to a YABBA */
    /* type */
    YABBA *foo(char *s);
Now we change the specification to this:
    /* The foo function performs a framitz function on the string that */
    /* is sent as the first argument using the second argument sent as */
    /* a filbert factor and returns a pointer to a YABBA type */
    YABBA *foo(char *s);
Note that we forgot to change the prototype.  Assuming that we correct the
actual function definition we will immediately see a problem when we do
the compile and the header file, which is self-documenting, is easily
fixed before we re-compile the functions that use the sub-system.

>Prototypes catch almost as many errors as lint would (they don't
>check data declarations), but they can also gloss over other
>potential errors (by quietly inserting casts to the correct type),

Exactly.  I can do the following:
    #include <stdio.h>
    ...
    int index;
    ...
    fseek(fp, index, SEEK_SET);
and not have to worry about the conversion.  Are you saying that it is
better for the programmer to cast noisily rather than have the compiler
do it quietly?

>and they do their work only when the programmer has gone to the
>considerable extra work of supplying the prototypes and keeping
>them up-to-date.

And I argue that the programmer should be making these design specifications
before coding.  Sure they may have to be modified as the project goes on
but that isn't nearly as difficult as you make it seem.

>aid of prototypes is essentially a two-pass affair: first you
>have to chase down all the "function called with no prototype in
>scope" warnings, and supply the missing prototypes so that a
>second pass can use them to check your calls.  How would you like
>it if you had to give a spellchecking program a list of the
>correctly-spelled words in the document to be checked?)

But you do have to do this.  Of course your vendor gives you a list
to start with but you have to add your own from time to time because
the list can never be complete.  If you mean the list has to be in the
actual document, of course that is the wrong place for them.  Just as
prototypes don't belong in the .c files.  They belong in a file that
can be included by the module defining the function as well as the
one(s) using it.  Of course you say essentially the same thing a few
paragraphs later so I'm not sure what the above statemet is meant to
suggest.

>The use of prototypes can also dramatically increase
>recompilation during development, because prototypes *must* be
>placed in header files (see below), so you need lots of header
>files (up to one per C source file), and they must be much more
>widely #included.  (It's true that in a carefully planned and

My experience suggests that the ratio of header files to source files
is much lower.  Usually a project can be broken up into broadly defined
subsections, each with it's own header/specification file.

>properly managed project, changes or additions to module
>interfaces, and therefore changes to prototypes and header files,
>should be infrequent.  On the other hand, incremental design and
>implementation is not without its merits, and new interfaces can
>be added all the time.)

And let's not forget clients who change their minds every other
day.  A properly managed project, even with prototypes and header
files, should be able to handle this.

>
>All prototypes (except those for static functions) must be

Just a side note here.  I hardly ever prototype static functions.  I
simply make sure that within a file a function is not used until it
has been defined.  This in effect makes it a prototype for itself.

>or incautious programmers who are typing prototypes directly in
>at the top of the .c files in which they are needed.  (Programming
>textbooks usually talk about functions before they talk about
>#include, so their early examples suggest and reinforce this

Which means that the methods of teaching C may need some overhaul.

>I'm not trying to start a lint vs. prototypes flamefest here.

Neither am I.  I hope that this doesn't come across as some sort of
personal attack.  I do agree with a lot of what you say and I have
no problem with those who are comfortable with lint using it.  I
simply happen to believe that there is a lot of value in prototypes
and wanted to show that there was another side to the question.

>Prototypes have their advantages, and they're definitely here to
>stay.  But they're not a panacea.

And neither is lint.  In the end the real issue is the capability of
the programmer using the tools.  Use the ones that you are comfortable
with and get to know them well.

-- 
D'Arcy J.M. Cain (darcy at druid)     |
D'Arcy Cain Consulting             |   There's no government
Toronto, Ontario, Canada           |   like no government!
+1 416 424 2871                    |



More information about the Comp.lang.c mailing list