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