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]

Reply via email to