"smart" cpp (was: Of Standards and Inventions: A Cautionary Tale)
Richard A. O'Keefe
ok at quintus.UUCP
Wed Apr 13 13:58:36 AEST 1988
In article <1528 at dataio.Data-IO.COM>, bright at Data-IO.COM (Walter Bright) writes:
> Here is a portion of a package to handle bit vectors in C. It demonstrates
> a reasonable use for allowing casts and sizeofs in preprocessor expressions.
...
> /* This code depends on 8 bit bytes. Put check in for this. */
> /* I don't care about 1's complement machines. */
> #if (unsigned char) -1 != 255
> #error "bytes are not 8 bits"
> #endif
That has never been portable, if only because a great many C preprocessors
do not support "#error". I tried something like this just now, and the
entire error message was
FOO.c: 1: undefined control
May I point out that there is no need to do everything in the preprocessor?
What distinguishes the C preprocessor from the incredibly hairy things in
PL/I (compile-time procedures), Burroughs Algol, and SAIL (see TOPLAS some
years ago), is that it is supposed to be small, fast, and cheap, so that
you can afford to use it all the time whether you need it or not.
If you need something more complicated than cpp can help with, you can
use M4 (there is a public domain M4 in the mod.sources archives), or you
can write a C program which generates a .h file or whatever. For example,
consider an FFT routine. You don't want to call sin() and cos() at run
time, but you can't rely on the compiler optimising cos(1.0/pow(2.0,6))
to a constant, and cpp can't do it. So you write a C program which calculates
the table and writes out the appropriate constants.
In this particular case, you might put something like
real-prog: real-prog.c defs.h
defs.h: mk-defs
mk-defs >defs.h
mk-defs: mk-defs.c
in a make-file (there are versions of 'make' for MS-DOS and VMS),
and the mk-defs.c program would have this test as perfectly ordinary C:
if ((unsigned char)(-1) != 255) {
fprintf(stderr, "unsigned char is not 8 bits\n");
exit(1);
}
More information about the Comp.lang.c
mailing list