correct code for pointer subtraction (short reply)
Eric Gisin
egisin at mks.UUCP
Thu Dec 22 10:30:06 AEST 1988
In article <2245 at iscuva.ISCS.COM>, carlp at iscuva.ISCS.COM (Carl Paukstis) writes:
> Eric: does this prototype declaration and return type satisfy your needs
> to avoid grepping through thousands of lines of code and changing same?
It was fairly easy to find relevant code, it was all of the form
... (ptr - array) ...
all I had to do was grep for "array".
The program was compiled large model, so "array" was implicitly "far*".
There was no way I could declare "array" huge,
the performance loss would be too great.
I had to change the code, and since this is a portable program
and I don't like scattering "#if PC" all over the place,
I defined a macro PTRDIFF(p,q) and replaced all occurences
of (ptr-array) with PTRDIFF(ptr,array).
There are several possible definitions for PTRDIFF:
#define PTRDIFF(p,q) (int)((TYPE huge*)(p) - (TYPE huge*)(q))
where TYPE has to be replaced with the type of p and q,
or
#define PTRDIFF(p,q) (int)(((long)(unsigned)(p) - (long)(unsigned)(q)) / sizeof(*q))
Both involve calls to library support functions, but
there is a more efficient definition of PTRDIFF that works
when p>=q holds (this was the case, I am deriving a non-negative
array index from a pointer to an array element). It is:
/* machine dependencies */
#if !PC
#define PTRDIFF(p, q) ((p) - (q))
#else
/* 8086 compiler writers are incapable of generating correct code */
#define PTRDIFF(p, q) (((unsigned)(p) - (unsigned)(q)) / sizeof(*q))
#endif
All it does is subtract the pointer offsets, resulting in an
*unsigned* (not signed) size_t which I then divide by the object's size.
More information about the Comp.lang.c
mailing list