Есть ли портативный способ узнать, определен ли uintptr_t в stdint.h?

Преамбула: я хочу преобразовать указатель в целочисленный тип, например проверить выравнивание. 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>

3

Решение

Если вы действительно хотите работать с реализацией, не обеспечивающей 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

Однако есть два недостатка:

  1. uintmax_t не может быть uintptr_t, важно для разрешения перегрузки и связывания.
  2. uintmax_t может быть больше, чем необходимо.
1

Другие решения

В целом, переносимые системы сборки в * nix, как правило, используют подход «autotools», который заключается в тестовой компиляции тривиального файла, содержащего рассматриваемый тип, и если он компилируется, вы знаете, что этот тип у вас есть. Если вы хотите что-то более простое, вы можете либо (а) предположить, uintptr_t доступно даже в C ++ (вероятно, разумно), или (б) использовать unsigned long long а потом:

static_assert(sizeof(unsigned long long) >= sizeof(void*), "oops");
1

Я знаю, что это очень старый, но, как насчет использования UINTPTR_MAX для тебя I_WONDER_IF_UINTPR_T_IS_DEFINED ?

1
По вопросам рекламы [email protected]