Marvin Humphrey wrote on 11/29/09 6:36 PM:
On Sat, Nov 28, 2009 at 08:58:04PM -0600, Peter Karman wrote:
There's already a PTR2I64 macro in Charmonizer/Probe/Integers, but we probably
need a larger menu:
PTR2I64
PTR2U64
PTR2I32
PTR2U32
PTR2SIZET
sounds reasonable.
Should pointers always be converted to unsigned types?
Sometimes if you're subtracting two pointers from each other, you need the
difference to be a signed result. The type "ptrdiff_t" exists for this
reason, but it's tricky to use correctly because you have to think about how
it gets upconverted on different systems.
http://blogs.msdn.com/david_leblanc/archive/2008/09/02/ptrdiff-t-is-evil.aspx
that's a good example.
My approach is to avoid ptrdiff_t altogether and always upconvert all operands
to i64_t before performing the arithmetic. For example[1]:
static INLINE i64_t
SI_tell(InStream *self)
{
FileWindow *const window = self->window;
i64_t pos_in_buf = PTR2I64(self->buf) - PTR2I64(window->buf);
return pos_in_buf + window->offset - self->offset;
}
yes, makes sense.
A thought: should we only define PTR2I32 and PTR2U32 on 32-bit systems?
They'd silently discard data on 64-bit systems. That would be bad.
We should force the programmer to either wrap the PTR2x32 conversion in an
#ifdef, or go through PTR2x64 first and then truncate with an explicit cast
which verifies their intent.
/* Assume that "start" and "end" cannot be more than I32_MAX apart. */
#if (SIZEOF_PTR == 4)
i32_t length = PTR2I32(end) - PTR2I32(start);
#else
i64_t a = PTR2I64(start);
i64_t b = PTR2I64(end);
i32_t length = (i32_t)(b - a);
#endif
yes, that seems sane.
Shall I have a go at this for my next task, or do you have something else in
mind?
--
Peter Karman . http://peknet.com/ . [email protected]