studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones c++ c++11 memory-alignment

c++ - para - manual de programacion android pdf



Consulta la alineación de una variable específica (3)

C ++ 11 introdujo el especificador de alignas para especificar la alineación de una variable y el operador de alineación para consultar la alineación predeterminada de un tipo. Sin embargo, no veo ninguna forma de obtener la alineación de una variable específica. Tomemos el siguiente ejemplo trivial:

alignas(16) float* array;

Esto es lo que podemos hacer al respecto:

  • alignof(float*) devuelve 8, que obviamente no es lo que queremos.
  • alignof(array) devuelve 16, que es exactamente lo que queremos, pero eso es una extensión del compilador; alignof como se especifica en el estándar no se puede utilizar en una variable específica.
  • alignof(decltype(array)) devuelve 8, que era bastante esperado, pero no lo que queremos.
  • std::alignment_of se implementa en términos de alignof , por lo que no ayuda mucho.

Me gustaría un mecanismo para confirmar que la array variables específicas está alineada en un límite de 16 bytes. ¿Hay algo en el estándar para realizar tal consulta?


Esto es manejado actualmente por EWG 98 . Envié un trabajo sobre esto:

El especificador de alignas es aplicable a los objetos, lo que afecta su requisito de alineación, pero no su tipo. Por lo tanto, actualmente no es posible determinar el requisito de alineación real de un objeto. Este artículo propone permitir la aplicación de alignof de objetos y referencias.

Lo mejor que puede hacer en este momento es definir una variable separada que contenga la alineación de la variable.


Puedes intentar con algo como:

bool is_aligned(const volatile void *p, std::size_t n) { return reinterpret_cast<std::uintptr_t>(p) % n == 0; } assert(is_aligned(array, 16));

Lo anterior supone un espacio de direcciones plano y esa aritmética en uintptr_t es equivalente a aritmética en char * .

Si bien estas condiciones prevalecen para la mayoría de las plataformas modernas, ninguna de las cuales es requerida por la norma.

Es totalmente posible que una implementación realice cualquier transformación al convertir void * a uintptr_t siempre que la transformación se pueda revertir cuando se uintptr_t desde uintptr_t a void * (consulte Qué es el tipo de datos uintptr_t ).

Más detalles en N4201 (propone, entre otras cosas, la operación is_aligned() ).

EDITAR

es volatile necesario aquí?

Permite algo como:

alignas(16) volatile float a; assert(is_aligned(&a, 16));

Sin volatile obtienes el error

no se conoce la conversión de ''flotación volátil *'' a ''const void *'' para el 1er argumento

Otras referencias:

  • ¿Por qué y cuándo se convierte en carbón volátil y necesario?
  • ¿Por qué es útil un puntero de punto a volátil, como "volatile int * p"?

Puedes intentar esto:

template<size_t size, typename T> constexpr bool IsAlignedAs(const T& v) { return (reinterpret_cast<const size_t>(&v) % size) == 0; } std::cout << IsAlignedAs<16>(array) << std::endl; std::cout << IsAlignedAs<32>(array) << std::endl;