It looks like the second is still valid C, but a C++11 compiler is allowed to break it if it declares "strict pointer safety" rules are in effect at runtime (which a GC implementation would presumably do)
Re:Baby's First Garbage Collector
by logancapaldo on Sunday December 08, 2013 @05:49PM
(#6871828)
What if it's not a DWIM compiler? I'm pretty sure (happy to be corrected) pointer <-> integer conversions are implementation defined. Therefore casting between could perform some reversible operation that ensured round tripping worked, but does not require that ptr(a - b) == a - b even though a == int(ptr(a)) holds.
I'm pretty sure (happy to be corrected) pointer <-> integer conversions are implementation defined.
Quite correct, subject to the requirement that converting the same uintptr_t value back to (void ) will return the original pointer. So the conversion could be implemented as a hash table if the compiler author wanted.
But if you look carefully at what I wrote, I'm never converting a value which was not previously returned by a (void )->(uintptr_t) conversion.
Re:Baby's First Garbage Collector
by logancapaldo on Sunday December 08, 2013 @08:22PM
(#6872391)
I see. What I was worried about was a version of the code you didn't actually write (casting the ptrdiff_t result to a [u]intptr_t, not casting the pointers first).
Right. You could also convert a pointer to a uintptr_t, XOR it with some value, then at some later point XOR it again to get back the original address and cast it back to a pointer and dereference it, and it would be legal despite breaking GC. However, a number of things that also break GC, like your first example, also happen not to be legal C even though they'll probably work on any existing implementation.
That's very close to the classical example of code that maims pointers: the doubly linked list that uses only one 'pointer' in each node (http://www.geeksforgeeks.org/xor-linked-list-a-memory-effici...)
Yes, but there's a legal way to do this.
reference the other two areas with offsets relative to the first area
If you cast the pointers to uintptr_t, and perform your arithmetic on uintptr_t and cast your final pointer back (void * ) before using it, what you've done is perfectly legal and safe (albeit weird) since uintptr_t is an unsigned integer type with all the flexibility of unsigned integers, and if x = (uintptr_t)p then it's guaranteed that p == (void * )x.
In other words:
is undefined behaviour, but is valid C (and has the same meaning on a DWIM compiler).