Если приложение скомпилировано для получения изображения x32, то в зависимости от типа целочисленного типа архитектура может иметь ширину в 16 бит, ширину 32 или более бит или что-то большее, чем 2 байта. Размер void*
будет 4 (на x32 всегда 4 ???). Это означало бы, что переход int
к void*
это хорошо, но если окажется, что на данной архитектуре void*
шире int
(который только гарантированно по меньшей мере, 2 байта по Стандарту), чем в лицеSafely cast void * to int
C Стандарт n1124 § 6.3.2.3 указатели
5 целое число может быть преобразовано в любой тип указателя. За исключением случаев, ранее указано, результат зависит от реализации, возможно, не быть правильно выровнены, может не указывать на сущности ссылочного типа, и может быть ловушка representation.56)
6 Любой тип указателя может преобразуется в целочисленный тип. За исключением, как указано ранее , результат определяется реализацией. Если результат не может быть представлен в целочисленном типе, поведение равно undefined. Результат не должен быть в диапазоне значений любого целочисленного типа .
литья void*
к int
может привести к неопределенному поведению в следующем фрагменте.
typedef enum tagENUM
{
WSO_1,
WSO_2,
//...
WSO_COUNT
} ENUM;
/* I cannot change handler signature because this is callback. I have to cast void*
* to ENUM however inside */
void handler(int i, int j, void *user_data)
{
ENUM mOperation;
mOperation = (ENUM)reinterpret_cast<int>(user_data);
}
// somewhere
handler(1, 2, (void*)WSO_1); // UB? We can imagine that someone passes to handler
// (void*)WSO_131072 which don't fit into 16 bits
// So is there a place opened for UB?
Если это правильно, что возможность для носовых демонах открыт - как же я тогда пишу thiss бросание безопасно? Могу ли я использовать intptr_t
, чтобы убедиться, что результат будет соответствовать?
void handler(int i, int j, void *user_data)
{
ENUM mOperation;
uintptr_t p_mOperation = reinterpret_cast<uintptr_t>(user_data);
if (p_mOperation > WSO_COUNT) {
send_error(conn, 500, http_500_error, "Error: %s", strerror(ERRNO));
return;
}
mOperation = static_cast<ENUM_WS_OPERATION>(p_mOperation); // now safe?
'void *' параметры * не * предназначены для передачи данных напрямую. Просто передайте целые числа * address * вместо значения, и вы в порядке. То, что вы пытаетесь, никогда не будет работать должным образом и является основной причиной медленного внедрения 64-бит в мире x86. – filmor
Я знаю, что могу, но мой вопрос о таком случае - есть ли место для UB? Я должен предположить, что кто-то мог пропустить НИЧЕГО за void * - как я могу предотвратить UB? – 4pie0
в цитируемой части четко сказано, что это * реализация определена *. –