﻿# How to correctly cast a pointer to int in a 64\-bit application?

The most general answer is – in no way\.

In 64\-bit programs, the size of the pointer is 64 bits, and cannot be put into the int type, which remains 32\-bit in almost all systems\. The only exception is exotic systems with the SILP64 [data model](https://pvs-studio.com/en/blog/terms/0012/), where the size of int is also 64 bits\. The most common operating systems \(Windows, Linux, macOS\) use the [LP64](https://pvs-studio.com/en/blog/terms/0028/) and [LLP64](https://pvs-studio.com/en/blog/terms/0026/) data models, where int is 32\-bit\.

Putting a 64\-bit pointer into a 32\-bit variable causes the cutting of high\-order bits, and therefore incorrect program behavior\. Code like this is invalid:

```cpp
void *ptr = ...;
int x = (int)ptr;
...
ptr = (void *)x;
```

This code is also dangerous because it hides an error that might reveal itself only in the long term\. As long as pointers refer to objects created inside low\-order bits of memory addresses, the program will work correctly, and perhaps for a long time\. But this is a deceptive impression of an operable application, and it could potentially crash at any moment \(see an [example](https://pvs-studio.com/en/blog/posts/cpp/0033/)\)\.

If, for some reason, the programmer needs to store pointers in integer types, he may use [memsize\-types](https://pvs-studio.com/en/blog/terms/0030/) for that – for instance, [intptr\_t](https://pvs-studio.com/en/blog/terms/0023/), [size\_t](https://pvs-studio.com/en/blog/terms/0044/), [INT\_PTR](https://pvs-studio.com/en/blog/terms/0024/), etc\.

However, there are specific cases when you may store a pointer in 32\-bit types\. I am speaking about handles which are used in Windows to work with various system objects\. Here are examples of such types: HANDLE, HWND, HMENU, HPALETTE, HBITMAP, etc\. Actually these types are pointers\. For instance, HANDLE is defined in header files as "typedef void \*HANDLE;"\.

Although handles are 64\-bit pointers, only the less significant 32 bits are employed in them for the purpose of better compatibility; for example, to enable 32\-bit and 64\-bit processes to interact with each other\. For details, see "[Microsoft Interface Definition Language \(MIDL\): 64\-Bit Porting Guide](https://msdn.microsoft.com/en-us/library/ms810720)" \(USER and GDI handles are sign extended 32b values\)\.

Such pointers can be stored in 32\-bit data types \(for instance, int, DWORD\)\. To cast such pointers to 32\-bit types, and vice versa, [special functions](https://msdn.microsoft.com/en-us/library/aa384267(VS.85).aspx) are used:

```cpp
void            * Handle64ToHandle( const void * POINTER_64 h ) 
void * POINTER_64 HandleToHandle64( const void *h )
long              HandleToLong    ( const void *h )
unsigned long     HandleToUlong   ( const void *h )
void            * IntToPtr        ( const int i )
void            * LongToHandle    ( const long h )
void            * LongToPtr       ( const long l )
void            * Ptr64ToPtr      ( const void * POINTER_64 p )
int               PtrToInt        ( const void *p )
long              PtrToLong       ( const void *p )
void * POINTER_64 PtrToPtr64      ( const void *p )
short             PtrToShort      ( const void *p )
unsigned int      PtrToUint       ( const void *p )
unsigned long     PtrToUlong      ( const void *p )
unsigned short    PtrToUshort     ( const void *p )
void            * UIntToPtr       ( const unsigned int ui )
void            * ULongToPtr      ( const unsigned long ul )
```

Note that simple errors of casting pointers to 32\-bit types are well diagnosed by the Visual C\+\+ compiler\. However, in many old projects which contain third\-party libraries, many compiler\-generated warnings are disabled, so, the probability of you missing such errors is greatly increased\. In the situation described, it is reasonable to use a specialized tool for providing portability of code to the 64\-bit platform – for instance, the [Viva64](https://pvs-studio.com/en/pvs-studio/) static code analyzer developed by our company\.

## References

1. Discussion at bytes\.com\. [Cast from void\* to int](http://bytes.com/topic/c/answers/482159-cast-void-int)
1. Andrey Karpov, Evgeniy Ryzhkov\. [64\-bit lessons\. Pattern 7\. Pointer packing](https://pvs-studio.com/en/blog/lessons/0015/)\.
1. Discussion at stackoverflow\.com\. [Error: cast from void\* to int loses precision](https://stackoverflow.com/questions/1640423/error-cast-from-void-to-int-loses-precision)\.
1. Andrey Karpov\. [About size\_t and ptrdiff\_t](https://pvs-studio.com/en/blog/posts/cpp/a0050/)\.
1. Knowledge Base\. [What is the POINTER\_32 macro?](https://pvs-studio.com/en/blog/posts/k0043/)