My guest is that it was originally created for VLM (Very Large Memory) in Alpha AXP, because Windows NT for Alpha is the first Windows with some 64-bit support. The OS is still 32-bit but it has the VLM API for applications to allocate large 64-bit memory if necessary, hence there must be some way to declare both 32 and 64-bit pointers in the same program
VLM returns POINTER_64
that the app has to store. POINTER_32
/__ptr32
are used by default, and POINTER_64
/__ptr64
will be used in 64-bit handling code
You can still even see some relics of AXP in Windows documentation and header files related to POINTER_32
POINTER_32
is defined in Ntdef.h and Winnt.h.
#ifdef (__AXP64__)
#define POINTER_32 _ptr32
#else
#define POINTER_32
#endif
Warning C4244
__AXP64__
is meant for Alpha AXP. You can also find lots of other references to Alpha AXP in Ntdef.h and Winnt.h even though Windows no longer runs on that platform
Because of this there are also POINTER_SIGNED
and POINTER_UNSIGNED
macros to specify how the 32-bit address is extended to the 64-bit one. They'll be expanded to __sptr
and __uptr
Another usage would be for 32-bit pointers when disabling LARGEADDRESSAWARE
in a 64-bit application
It's exactly the same as x32 ABI in Linux where long
and pointers are 32-bit wide
By default, 64-bit Microsoft Windows-based applications have a user-mode address space of several terabytes. For precise values, see Memory Limits for Windows and Windows Server Releases. However, applications can specify that the system should allocate all memory for the application below 2 gigabytes. This feature is beneficial for 64-bit applications if the following conditions are true:
- A 2 GB address space is sufficient.
- The code has many pointer truncation warnings.
- Pointers and integers are freely mixed.
- The code has polymorphism using 32-bit data types.
All pointers are still 64-bit pointers, but the system ensures that every memory allocation occurs below the 2 GB limit, so that if the application truncates a pointer, no significant data is lost. Pointers can be truncated to 32-bit values, then extended to 64-bit values by either sign extension or zero extension.
Virtual Address Space
When setting /LARGEADDRESSAWARE:NO
the size of pointers are still 64-bit wide even though the high 32 bits has no significant values. Therefore to save memory for the pointer we must declare them as POINTER_32
See How to detect X32 on Windows?