On Sep 2, 2009, at 04:08, Ludovic Courtès wrote:
In the Guile case, I'm a tiny bit concerned about some of the
pointer/
int games played (e.g., I'm pretty sure C99 does not guarantee that
you can convert an arbitrary uintptr_t value to pointer and back and
be guaranteed of getting the original value... but I don't know of a
platform that actually violates that assumption), but only a tiny
bit.
Really? I think the whole purpose of `uintptr_t' is to allow that,
isn't it?
It's the other way around that's guaranteed to work: void* ->
(u)intptr_t -> void*. So any value originally derived from a valid
pointer will work, but arbitrary values may not. Also, C99 talks
about uintptr_t as being capable of holding a converted pointer-to-
void; strictly speaking, I don't think it requires that a direct
conversion from/to any other pointer type (except possibly char*) work
the same way.
So, for example, uintptr_t may have 64 bits on a machine that uses 48-
bit pointers (segment+offset? also, some embedded processors have non-
power-of-two pointer or integer sizes, though I don't know whether
they have pointer and int types matching in size); pointers may have
trapping representations (invalid segment number?); storing an integer
value into a pointer register may cause certain bits to be masked off;
manipulation of pointer values in general registers may not preserve
bits known by the compiler not to be set in any valid or null
pointers; etc.
And then there's the whole NULL-vs-0 thing -- "0" is a null pointer
constant in source code, but strictly speaking the compiler produces a
null pointer constant there; it doesn't imply that the null pointer
has the same binary representation as 0, nor that a non-constant zero
value when cast to a pointer will be a null pointer, nor that memset(,
0,) gives you null pointers, nor that a null pointer cast to uintptr_t
will have the value 0, etc.
(For example, in an architecture with one pointer format for segment +
word offset, and a second representation for segment + word offset +
bit offset into word, a void* may require the second form, but a
struct pointer might use the former, if all structs are required to be
word-aligned. And converting a pointer to uintptr_t could just copy
bits around, giving consistent results only if you use the same
pointer form consistently in the conversions. And all-bits-zero may
store an invalid segment number that could lead to a trap when loaded
into a pointer register, and a "null pointer" may be represented with
a reserved non-zero segment number. This is not completely
theoretical... I once used a platform with multiple pointer types and
a null pointer representation using segment number -1, which could be
loaded without faulting but not dereferenced, but I'm rusty on some of
the details, and never got familiar with the C environment on it.)
Like I said, most platforms I know of, and all I know of that we're
likely to care about, will still meet these assumptions to the best of
my knowledge, so it's probably not a big problem. But as a bit of a
language pedant, I did notice...
Ken