typedefs, functions returning pointers to functions
Steve Summit
stevesu at azure.UUCP
Thu Dec 22 08:26:47 AEST 1983
What in the world do people have against typedefs? They make
code quite a bit more readable and portable. I was glad when
people started pointing them out to me. (So what if the
implementation is a bit baroque? It has to be.)
getroutine, the module of mine that started this whole
discussion, used to start out
int (*getroutine(name, table))()
which is rather unreadable and also violates the convention that
routine names should begin in column 1 so they can be easily
found with an editor. (Writing
int (*
getroutine(name, table))()
looks pretty weird, with the unmatched parentheses.) getroutine
now starts out
FUNCPTR
getroutine(name, table)
which is quite a bit more readable. (FUNCPTR, for those of you
who have somehow missed the fourteen articles on the subject, is
defined as
typedef int (*FUNCPTR)();
The new type FUNCPTR also cleared up another problem: getroutine
has two distinct error returns, NULL and -1. (I'm banking on the
fact that -1 will probably never be a valid pointer. If you want
to flame about this, flame about signal(2) too.) Although the 11
compilers would let me say
return(-1);
the vax compilers (correctly) generate an "incompatible
integer/pointer" warning. I'm not sure what the proper cast
would be; it would probably be something horrendous like
return((int *())(-1))
Again, it's not at all obvious what that means. The typedef
version is clear:
return((FUNCPTR)(-1));
Rob Warnock relates a similar function pointer declaration
problem which he "finally solved using typedefs, but wasn't
happy, since there seemed something inelegant about that." He
then demonstrates (somewhat proudly, it seems) a program which
"does it WITHOUT typedefs" although he admits that "the typedef
version is easier to read, and was what was used in production."
Read carefully! The line that starts "struct..."
is actually declaring "state".
struct foo { struct foo (*(*dummy)())[]; } (*state)[];
Note that the "line that starts 'struct...'" does not even have a
comment! If came across a line like that in a piece of code I
was trying to modify or debug, I'd weep. Then I'd curse the
programmer who had the gall to write it. (Sorry to pick on you,
Rob, but there's an important point here.) C programmers have a
bad reputation for writing cryptic, unreadable, hackish code.
Examples like this make that reputation well-deserved.
PARTICULARLY when the compiler generates identical instructions
(as Rob assures us it does) PLEASE PLEASE write readable code!
Everyone will benefit (except maybe you, if you happen to be on a
power trip trying to confuse everybody else.)
I always write
while(*p++ != '\0')
instead of
while(*p++)
even though I know they do the same thing. Sure, the "!= '\0'"
isn't strictly necessary in this case, but I always have to look
twice at lines like the second one. The first one is more
natural. Only if you blindly equate "elegant" with "minimal" is
the second one more "elegant."
I once had points taken off on a programming assignment for
writing something like
if(a == b) return(TRUE);
else return(FALSE);
The grader said I should have "more succinctly" said
return(a == b);
I realize now that he was wrong, and I wish I'd realized it then,
and called him on it. He was obviously a fully indoctrinated
member of the "hacks are beautiful" school. Those two fragments
do do the same thing, and this is a case where the second one
might even generate slightly more efficient code. But I have to
look at something like "return(a == b)" twice or even three times
to convince myself that it's identical to what I conceptualize as
"if a equals b it's true, otherwise it's not." Why make things
difficult? I know the idiom, and it still gets in my way.
Someone who had never seen it might never figure out what it did.
(I remember spending fifteen minutes explaining to a friend in an
introductory programming class how return(a == b) worked.)
Sorry this got so long. Cryptic, hackish code is just so ugly,
while clean, modular, readable code can be truly elegant.
Steve Summit
tektronix!tekmdp!stevesu
More information about the Comp.lang.c
mailing list