2011-02-16 15 views
9

Quiero realizar un control para la alineación de memoria de algún tipo T. La forma más sencilla de hacer esto esuintptr_t alternativa portátil

if (((uintptr_t)&var & __alignof(T) - 1) == 0) ... 
embargo

, uintptr_t no es parte de la existente C++ estándar y no es compatible con algunos compiladores, así que estoy buscando una manera alternativa portátil para hacer esto y std::ptrdiff_t se ve bien para mi. std::ptrdiff_t garantizado para poder almacenar la diferencia entre dos punteros, pero ¿quién dice que uno de esos punteros no puede ser un puntero nulo? En ese caso, std::ptrdiff_t debe tener al menos el mismo tamaño que el puntero.

template <typename T> bool is_properly_aligned(const T* const ptr) 
{ 
    std::ptrdiff_t diff = (ptr - static_cast<T*>(0)) * sizeof(T); 
    return ((diff & __alignof(T) - 1) == 0); 
} 

o así (para deshacerse de la multiplicación por sizeof(T))

template <typename T> bool is_properly_aligned(const T* const ptr) 
{ 
    std::ptrdiff_t diff = 
     reinterpret_cast<const char*>(ptr) - static_cast<const char*>(0); 
    return ((diff & __alignof(T) - 1) == 0); 
} 

¿Qué piensa acerca de este tipo de solución? ¿Es lo suficientemente portátil? No veo ninguna razón por la cual esto debería fallar, sin embargo, me gustaría confirmarlo.

Gracias.

Respuesta

1

No estoy seguro de cuál es la pregunta aquí. "¿Qué piensas?" Creo que ptrdiff_t es de hecho el tipo de datos correcto para representar la diferencia entre dos punteros, pero tiene muy poco sentido comparar dos punteros si no apuntan a un bloque de memoria contigua que proviene de una asignación simple (y como corolario, ninguno de los dos indicadores que se comparan debe ser NULL).

+0

Usted escribió 'Creo que ptrdiff_t es de hecho el tipo de datos correcto para representar la diferencia entre dos punteros'. Mi pregunta es, ¿qué piensas, es portátil almacenar la representación de entero de puntero en ptrdiff_t? – ledokol

+0

Usted escribió 'pero tiene muy poco sentido comparar dos punteros si no apuntan a un bloque de memoria contigua que proviene de una asignación simple'. No estoy comparando, estoy calculando la distancia y el propósito de esto es obtener una representación entera del puntero. – ledokol

+0

Pero ptrdiff_t no es un tipo numérico como int. Ni siquiera está garantizado que tenga el mismo tamaño que int (y en los sistemas de 64 bits, generalmente no lo es). Si quieres jugar así, también puedes lanzar (int) ptr y verificar los bits más bajos para alinear. – Enno