Prototyping in an imperfect world....
Adam Stoller
ghoti+ at andrew.cmu.edu
Sat Jun 30 08:58:59 AEST 1990
(lengthy - but lot's of white-space -- sorry)
Some of this is old news, but some may not be - and I'm a bit interested
in some [reasonable] opinions on either....
[prolog (harmonicas playing in the background?)]
As many of us are aware - there is a wonderful thing called prototyping
-- especially with respect to ANSI-C. Unfortunately we are also aware
that while some people on some platforms may have full prototyping
abilities others may not -- and this tends to cause problems for people
who'd like to try and make their code portable....
There are two different places where this comes into effect:
1) extern reference declarations
2) function definitions
The first I believe has been reasonably well addressed. For those not
familliar with a way to easily handle it I provide the following
[possible] definition:
/* external reference declarations */
/* use: extern int foo P_((int x, char c, long d)); */
#ifdef __STDC__
#define P_(args) args
#else
#define P_(args) ()
#endif
A hack? Yes, but a farily clean and reasonable one (IMO).
The second situation however I haven't seen addressed much. About the
only way I've seen people deal with it was by doing something like:
int
#ifdef __STDC__
foo(int x, char c, long d)
#else
foo(x, c, d)
int x;
char c;
long d;
#endif
{
....
}
This, IMO, is both a painful (to implement/maintain) and ugly hack - and
one which I'd like to avoid if possible.
To this end - one of the people I work with came up with the idea for a
macro to use for the definitions - which I'd like to share with you now
and get some opinions on:
#ifdef __STDC__
#define PP_(a) (
#define V_ void)
#define S_ ,
#define E_ )
#else
#define PP_(a) a
#define V_
#define S_ ;
#define E_ ;
#endif
This allows the above example to be defined like:
int foo PP_((x, c, d))
int x S_
char c S_
long d E_
{
......
}
Or
int foo PP_(())
V_
{
....
}
Which for the most part is reasonably close to the old-style definitions
though nevertheless hackish.
[Question Time]
Q-1) Is it too ugly for words ?
Personally, I admit not liking the loss of the
commas/semicolons which are pretty much second-nature when
typing in the code, but other than that it doesn't bother me
too much.
Q-2) Is it too hackish to be considered reasonable ?
I think it stays within the boundary of reasonable hacks
(whatever that boundary may be, unless you're a purist who
considers any hack evil??)
Q-3) Is it reasonably maintainable ?
It suffers a little of the same problem as the earlier #ifdef
example - in that there are still two places where the name and
number of arguments must be maintained - but I think this one
wears a little better in that it's really only as bad(?) as the
old-style definitions.
Q-4) Can it be made better ?
Mostly I mean this in terms of the symbols chosen for the
macros, and possibly the macros themselves. Certainly there
are tons of alternatives ("use A_ instead of S_", etc) - but
I'm looking for something a bit more substantial, with
reasonable explanation. (hey, it's always possible that we
might have gotten it "right" the first time....:-)
(FYI: V_ == void, S_ == separator, E_ == end-of-list)
[Visualization]
(some blank lines removed from preprocessor output)
[ | <-column 0]
----------------
> cat foo.c
/* #define's as shown above */
int fname PP_((a1, a2))
int a1 S_
int a2 E_
{
}
struct lconv *ansi_localeconv PP_(())
V_
{
}
----------------
> cc -E -D__STDC__ foo.c
int fname (
int a1 ,
int a2 )
{
}
struct lconv *ansi_localeconv (
void)
{
}
----------------
> cc -E -U__STDC__ foo.c
int fname (a1, a2)
int a1 ;
int a2 ;
{
}
struct lconv *ansi_localeconv ()
{
}
----------------
More information about the Comp.lang.c
mailing list