metrica
Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

Шаг 2
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности
close form
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Бесплатная лицензия PVS‑Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
check circle
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

Вебинар: Трудности при интеграции SAST, как с ними справляться - 04.04

>
>
>
Как корректно привести указатель к int …

Как корректно привести указатель к int в 64-битной программе?

05 Апр 2013

Наиболее общий ответ - никак.

В 64-битных программах размер указателя равняется 64-битам и его нельзя поместить в тип int, который остался 32-битным практически на всех системах. К исключению относятся экзотические системы с моделью данных SILP64, где размер int также 64-битный. В наиболее распространенных операционных системах (Window, Linux, macOS, ...) используются модели данных LP64 и LLP64, в которых int занимает 32-бита.

Помещение 64-битного указателя в 32-битную переменную ведет к обрезанию старших разрядов и как следствие к некорректной работе программы. Подобный код в программах недопустим:

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

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

Если по каким-то причинам программисту необходимо хранить указатели в целочисленных типах, то для этого он может использовать memsize-типы, например, intptr_t, size_t, INT_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" (USER and GDI handles are sign extended 32b values).

Такие указатели можно хранить в 32-битным типам данных (например, int, DWORD). Для преобразования таких указателей к 32-битным типам и обратно используются специальные функции:

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 )

Следует отметить, что простые ошибки приведения указателей к 32-битным типам хорошо диагностируются компилятором Visual C++. Однако во многих старых проектах, содержащих большие сторонние библиотеки, часто бывают отключены многие предупреждения компилятора, что увеличивает вероятность пропуска такого типа ошибок. В описанной ситуации имеет смысл использовать специализированное средство обеспечения переносимости кода на 64-разрядную платформу, например разработанный нами статический анализатор кода Viva64.

Библиографический список

Популярные статьи по теме


Комментарии (0)

Следующие комментарии next comments
close comment form