e.g. x+y becomes (x + y | (1<<63))
Or does the loss of overflow detection hurt you more?
e.g. x+y becomes (x + y | (1<<63))
Or does the loss of overflow detection hurt you more?
Pointers are guaranteed to have LSB of zero because of data is typically aligned to the machine word size rather than individual bytes. In this case, that is enforced (or at worst everything must be 16-bit aligned).
It's a pretty clever idea really.
Except pointers to functions in ARM thumb. Or more simply pointers inside strings.
void a(int *b)
{
*b = 5;
}
struct c
{
int d;
};
int main()
{
struct c foo;
a(&foo.d); // no way to do this in Java!
printf("%lu\n", (unsigned long)foo.d);
}There's nothing that requires any particular alignment on x86/x64 either, but it's standard for most compilers because it makes everything run faster at minimal size cost.
The actual instructions are aligned on an even byte boundary; however, on AArch32, encoding interoperability is achieved with BLX or BX, which uses the low bit as a tag value: 0=A32, 1=T16/32. However, in a lisp interpreter, e.g., you should never find a function pointer in an "object" context; i.e., something which could be an integer instead.
IIRC, you can do this just by checking if it is less than zero.
tl;dr: all valid pointer values are possible, regardless of how much memory you actually have.
And, when you get down to the assembly level, it doesn't matter - you can treat an unsigned integer as signed for a comparison if it makes things easier.
That may be rare nowadays (or is it? I remember reading recently that some 64-bit CPU chose to preferably use a memory range from -2GB to +2GB. AMD64?), but whether there is is outside of the control of most language implementers. They can control their own memory allocator, though, and guarantee that it never stores 64-bit quantities at odd addresses.