web-dev-qa-db-fra.com

Comment vérifier si un pointeur pointe vers un emplacement mémoire correctement aligné?

Donné un void * à un certain stockage, comment vérifier s'il pointe vers un stockage correctement aligné sans aucun comportement défini par l'implémentation?

Bien sûr, nous avons std::align , mais existe-t-il un moyen plus efficace de le faire?

template <std::size_t alignment>
inline bool is_aligned(void * ptr) noexcept {
    std::size_t max = 1u;
    return std::align(alignment, 1u, ptr, max);
}

PS: je dois le faire d'une manière compatible avec les normes C++, sans compter sur des hacks spécifiques à la plate-forme (définis par l'implémentation).

PPS: Je m'excuse pour mon (compréhension de) l'anglais, ce n'est pas ma langue maternelle.


EDIT (2018.08.24): Supprimé "efficace" du titre, ajouté encore plus de mots pour souligner que je ne veux pas d'implémentation définie ou de plateforme -comportement spécifique.

31
jotik

Si le reste n'est pas nul lors de la division de l'adresse avec l'alignement souhaité, l'adresse n'est pas alignée.

inline bool
is_aligned(const void * ptr, std::uintptr_t alignment) noexcept {
    auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
    return !(iptr % alignment);
}

Cependant, cela ne peut pas être constant, en raison de la distribution.

En outre, cela repose sur le fait défini par l'implémentation que la conversion du pointeur en entier doit conserver la représentation numérique de l'adresse. Comme le soulignent les commentaires, cela n'est pas garanti par la norme, donc cette fonction n'est pas nécessairement portable sur toutes les plateformes. Cela est également vrai, car il est facultatif pour l'implémentation de fournir std::uintptr_t.


Je m'attendrais à ce que cela ne soit nécessaire que lors de l'alignement d'un type, donc cela pourrait être plus pratique:

template<class T>
bool
is_aligned(const void * ptr) noexcept {
    auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
    return !(iptr % alignof(T));
}
20
eerorika