Есть ли переносимый способ узнать, определена ли uintptr_t в stdint.h?
Преамбула: я хочу преобразовать указатель в целочисленный тип, например. для проверки выравнивания. uintptr_t
кажется правильным, но он гарантирован только в 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: Я знаю, чем в С++ 11 Я должен использовать alignof
вместо sizeof
Примечание 2: Я знаю об этом обсуждении: <cstdint> vs < stdint.h >
Ответы
Ответ 1
Если вы действительно хотите работать с реализацией, не предоставляющей 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
может быть больше, чем необходимо.
Ответ 2
В целом, портативные системы сборки на * nix имеют тенденцию использовать подход "autotools", который заключается в том, чтобы протестировать компиляцию тривиального файла, содержащего соответствующий тип, и, если он компилируется, вы знаете, что у вас есть этот тип. Если вы хотите что-то более простое, вы можете либо (a) предположить, что uintptr_t
доступен даже в С++ (возможно, разумно), или (b) использовать unsigned long long
, а затем:
static_assert(sizeof(unsigned long long) >= sizeof(void*), "oops");