V1091. The pointer is cast to an integer type of a larger size. Casting pointer to a type of a larger size is an implementation-defined behavior.
Анализатор обнаружил приведение указателя к интегральному типу большего размера. Результат может отличаться от ожидаемого программистом.
Согласно стандартам C и C++, результат такого выражения зависит от реализации. Ожидаемый программистом результат в большинстве реализаций будет совпадать тогда, когда указатель приводится к интегральному типу того же размера.
Рассмотрим следующий синтетический пример:
void foo()
{
const void *ptr = reinterpret_cast<const void *>(0x80000000);
uint64_t ui64 = reinterpret_cast<uint64_t>(ptr); // <=
}
В примере указатель 'ptr' преобразуется в тип 'uint64_t', имеющий размер 8 байт. На 32-битной платформе размер указателя равен 4 байтам. Результат такого преобразования зависит от реализации компилятора.
Так, если используется компилятор GCC или MSVC, то в переменную 'ui64' будет записано число 0xffff'ffff'8000'0000. В то же время Clang запишет число 0x0000'0000'8000'0000.
Чтобы преобразовать 32-битный указатель в 64-битное число и избежать поведения, определённого реализацией, нужно сделать следующее:
- Преобразовать 32-битный указатель к 32-битному числу
- Преобразовать полученное 32-битное число к 64-битному числу
Для исправления сначала преобразуем указатель к 'uintptr_t'. Это целочисленный беззнаковый тип, размер которого всегда равен размеру указателя. Затем полученное 32-битное число преобразуем к 64-битному. Исправленный код:
void foo()
{
const void *ptr = reinterpret_cast<const void*>(0x80000000);
uint64_t ui64 = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr));
}
Данная диагностика классифицируется как:
|