﻿# V205\. Explicit conversion of pointer type to 32\-bit integer type\.


> Это правило входит в группу "Диагностика 64\\\-битных ошибок"\\\. Разработка правил этой группы больше не ведётся, и в будущем они могут быть отключены\\\. Если вы используете эти правила, \[свяжитесь с нашей поддержкой\]\(https://pvs\-studio\.ru/ru/about\-feedback/\) — мы поможем найти замену или предложим альтернативное решение\\\.

Анализатор обнаружил явное приведение указателя к 32\-битному целочисленному типу\. Ранее подобную ситуацию можно было выявить с помощью диагностического правила V202\. Однако явное приведение указателя к типу int, гораздо опаснее, чем приведение intptr\_t к типу int\. Поэтому было создано отдельное правило для поиска явного приведения типов при работе с указателями\.

Пример некорректного кода\.

```cpp
int n;
float *ptr;
...
n = (int)ptr;
```

В 64\-битной программе тип `int` имеет размер 4 байта и не может вместить в себя указатель размером 8 байт\. Приведение типа, как показано в примере, практически всегда свидетельствует о наличии ошибки\.

Отметим, что такие ошибки очень неприятны тем, что могут не сразу проявить себя\. Программа может хранить указатели в 32\-битных переменных и некоторое время корректно работать, пока все создаваемые в программе объекты располагаются в младших адресах оперативной памяти\.

Если по каким\-то причинам необходимо хранить указатель в переменной целочисленного типа, то для этого следует использовать [memsize\-типы](https://pvs-studio.ru/ru/blog/terms/0030/) данных\. Например: `size_t`, `ptrdiff_t`, `intptr_t`, `uintptr_t`\.

Пример корректного кода:

```cpp
intptr_t n;
float *ptr;
...
n = (intptr_t)ptr;
```

Возможна специфическая ситуация, когда указатель допустимо хранить в 32\-битных типах\. Речь идет о дескрипторах \(handles\), которые используются в Windows для работы с различными системными объектами\. Примеры таких типов: `HANDLE`, `HWND`, `HMENU`, `HPALETTE`, `HBITMAP` и так далее\. По сути, эти типы являются указателями\. Например, HANDLE объявляется в заголовочных файлах как `typedef void *HANDLE;`\.

Хотя дескрипторы являются 64\-битными указателями, для большей совместимости \(например, для возможности взаимодействия между 32\-битынми и 64\-битными процессами\) в них используется только младшие 32\-бита\. Подробнее об этом можно прочитать здесь: "[Microsoft Interface Definition Language \(MIDL\): 64\-Bit Porting Guide](https://learn.microsoft.com/en-us/previous-versions/ms810720(v=msdn.10))" \(USER and GDI handles are sign extended 32b values\)\.

Такие указатели можно хранить в 32\-битных типах данных \(например, `int`, `DWORD`\)\. Для преобразования таких указателей к 32\-битным типам и обратно используются [специальные функции](https://learn.microsoft.com/en-us/windows/win32/winprog64/the-tools):

```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 )
```

Рассмотрим пример:

```cpp
HANDLE h = Get();
UINT uId = (UINT)h;
```

Анализатор не выдаёт здесь сообщение, хотя HANDLE — это указатель\. Его значения всегда помещаются в 32\-бита\. Следует учитывать, что невалидные дескрипторы \(handles\) объявлены следующим образом:

```cpp
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
```

Поэтому некорректно ниже будет написать так:

```cpp
if (HANDLE(uID) == INVALID_HANDLE_VALUE)
```

Т\.к\. переменная `uID` беззнаковая, то значение указателя будет равно не 0xFFFFFFFFFFFFFFFF, а 0x00000000FFFFFFFF\.

Для подозрительной проверки, где unsigned будет превращаться в указатель, будет выдано предупреждение [V204](https://pvs-studio.ru/ru/docs/warnings/v204/)\.