Преамбула: я хочу преобразовать указатель в целочисленный тип, например проверить выравнивание. uintptr_t
кажется, правильный тип, но это гарантировано только в C, а не в C ++ (или C ++ 11)
Для следующего кода:
#include <stdint.h>
#ifndef I_WONDER_IF_UINTPR_T_IS_DEFINED
typedef unsigned long uintptr_t;
#endif
template <typename T>
bool isAligned(unsigned char* p) ///Checks alignment with respect to some data type
{
return !((uintptr_t) p % sizeof(T));
}
template bool isAligned<uint16_t>(unsigned char* p);
template bool isAligned<uint32_t>(unsigned char* p);
template bool isAligned<uint64_t>(unsigned char* p);
2 вопроса:
I_WONDER_IF_UINTPR_T_IS_DEFINED
?unsigned long
и забыть об этом?Сгенерированная сборка (когда доступно uintptr_t): http://goo.gl/4feUNK
Примечание 1: я знаю, чем в C ++ 11 я должен использовать alignof
на месте sizeof
Примечание 2: мне известно об этом обсуждении: <cstdint> против <stdint.h>
Если вы действительно хотите работать с реализацией, не обеспечивающей uintptr_t
когда в том числе <stdint.h>
рассмотрите возможность использования uintmax_t
вместо этого и static_assert
для пригодности (вы уже установили, что вы можете быть на тупой установке, так что она может быть слишком маленькой):
#include <stdint.h>
static_assert(sizeof(uintmax_t) >= sizeof(void*), "need a bigger unsigned type.");
// Add code using `uintmax_t` to round-trip data-pointers here
Однако есть два недостатка:
uintmax_t
не может быть uintptr_t
, важно для разрешения перегрузки и связывания.uintmax_t
может быть больше, чем необходимо.В целом, переносимые системы сборки в * nix, как правило, используют подход «autotools», который заключается в тестовой компиляции тривиального файла, содержащего рассматриваемый тип, и если он компилируется, вы знаете, что этот тип у вас есть. Если вы хотите что-то более простое, вы можете либо (а) предположить, uintptr_t
доступно даже в C ++ (вероятно, разумно), или (б) использовать unsigned long long
а потом:
static_assert(sizeof(unsigned long long) >= sizeof(void*), "oops");
Я знаю, что это очень старый, но, как насчет использования UINTPTR_MAX
для тебя I_WONDER_IF_UINTPR_T_IS_DEFINED
?