MathuSum Mut
MathuSum Mut

Reputation: 2825

Use case for POINTER_SIGNED or POINTER_UNSIGNED?

On Windows in BaseTsd.h, there are two macros: POINTER_SIGNED and POINTER_UNSIGNED, which resolve to __sptr and __uptr respectively. According to Microsoft's documentation, these are directives that specify "how the compiler converts a 32-bit pointer to a 64-bit pointer".

__sptr, which is the default, treats the pointer as signed and converts it to 64-bit as such, so negative pointers are extended as negative, but this has the effect of incorrectly treating the most significant bit as the sign bit, which may not be desired in some cases.

Hence __uptr was created, where the pointer is treated as unsigned instead, and is extended as unsigned. Now, I am having trouble understanding what situations can come up that would require such constructs, and how one would discern which would be most suitable.

What is the advantage of using __ptr32 instead of casting from int or unsigned int to a pointer and dereferencing as you would on a 64-bit platform? Both would generally invoke undefined behavior, right? How would one choose between __sptr and __uptr?

Upvotes: 0

Views: 236

Answers (1)

Alex Guteniev
Alex Guteniev

Reputation: 13759

32-bit pointer are only meant as porting aid for legacy code. Maybe they are also used by Microsoft inside the implementation Wow64 layer, but it's only a guess.

You can have 32-bit pointers working in 64-bit application, if you disable Large Address Aware flag (with Visual Studio, you do this with corresponding Linker option). Then, all allocation will be restricted to 2 GB. This would sorta defeat the purpose of having 64-bit application, but may help you port some old crap to x64 quickly.

And anyway having 32-bit pointers as pointers is cleaner than 32-bit int, since it's clear that the value contains pointer, not arbitrary value.

Regarding signed/unsigned. I'm not sure, but I have the following guess:

Typically with 32-bit apps and 32-bit OS, lower addressable 2 GB is programs' virtual address space, upper addressable 2 GB is kernel space. In 64-bit OS kernel space is very top terabytes of 64-bit space. So, signed pointer conversion would convert application's space to application's space and prohibited space to prohibited space.

But when you've enabled Large Address Aware for your 32-bit app and /3GB switch for 32-bit OS, you have some more of application's space (up to 3 GB), then to correctly convert all application's pointers, you'd prefer unsigned type.

Upvotes: 1

Related Questions