2016-10-03 2 views
0

En essayant de répondre à another question, j'ai proposé une solution qui utilise std::memcpy() pour stocker des types génériques dans un tampon de char s.Anciennes données plaines et problèmes d'alignement `std :: memcpy`

Mon doute est sur les problèmes d'alignement de mémoire possibles stockant POD (je sais que avec le type non-POD, comme std::string, est très très dangereux).

En résumé: le programme suivant rencontre-t-il des problèmes d'alignement mémoire? Et s'ils le sont, il est possible d'écrire quelque chose de similaire (qui stockent les valeurs POD dans un tampon char) qui est sûr? Et comment?

#include <cstring> 
#include <iostream> 

int main() 
{ 
    char buffer[100]; 

    double d1 { 1.2 }; 

    std::memmove(buffer + 1, & d1, sizeof(double)); 

    double d2; 

    std::memmove(& d2, buffer + 1, sizeof(double)); 

    std::cout << d2 << std::endl; 

    return 0; 
} 
+0

Cela devrait fonctionner. En général, vérifiez sizeof() moins que le tampon fixe, mais bien sûr, un double est beaucoup moins que le 100 utilisé ici. – Gregg

+0

@Gregg - Bien sûr; J'ai utilisé '100' pour éviter les doutes sur la taille du tampon. – max66

Répondre

5

Ceci est sûr.

[basic.types]/2: Pour tout type trivialement copiable T, si deux pointeurs vers T points à T distincts objets obj1 et obj2, où ni obj1 ni obj2 est un sous-objet de classe de base, si les octets sous-jacents (1,7) constituant obj1 sont copiés en obj2, obj2 doivent par la suite avoir la même valeur que obj1.

Puisque double est trivialement copiable, votre code est bien défini.

3

Vous pouvez copier vers et à partir d'un tampon non aligné. Ce que vous ne pouvez pas faire est de lancer le tampon en double * et ensuite opérer directement sur la valeur en mémoire, comme un double. Cela provoquera souvent une erreur en raison de problèmes d'alignement.

+2

"* L'assignation technique d'octets aléatoires à un caractère n'est pas définie en raison des représentations d'interruptions. *" Non conforme à la norme. [basic.types]/2 dit que vous pouvez utiliser 'char' ou' unsigned char' pour la copie triviale d'objets. –

+0

Donc, c'est un petit problème dans la norme. char est autorisé une représentation de piège et l'une des clauses doit être incorrecte. En fait, l'auteur a hoché la tête et le type doit être non signé char. –

+1

Il n'y a pas de problème. 'char' est autorisé à être signé ou non signé. 'char signé 'peut ou non avoir une représentation de piège. Pour qu'une implémentation soit conforme à la norme, si 'char signé 'peut piéger, alors' char' * ne doit pas être signé *. Donc un complément de 2 signé du type 'char' est parfaitement valide. Il y a d'autres endroits dans la norme avec une telle exigence, comme les exigences UTF-8 sur 'char' (être capable de convertir tout code UTF-8 entre' char' et 'unsigned char' nécessite' char' pas trap). –