﻿# V204\. Explicit conversion from 32\-bit integer type to pointer type\.


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

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

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

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

В 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;
...
ptr = (float *)(n);
```

Возможна специфическая ситуация, когда указатель допустимо хранить в 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://docs.microsoft.com/en-us/previous-versions/ms810720(v=msdn.10))" \(USER and GDI handles are sign extended 32b values\)\.

Такие указатели можно хранить в 32\-битных типах данных \(например, `int`, `DWORD`\)\. Для преобразования таких указателей к 32\-битным типам и обратно используются [специальные функции](https://docs.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 )
```