Partage
  • Partager sur Facebook
  • Partager sur Twitter

Taille d'un objet ≥ sa contrainte d'alignement ?

    23 avril 2022 à 17:36:44

    Salut tout le monde !

    Je ne comprends pas ce qui est affiché par ce code que j'ai implémenté :

    #include <iostream>
    
    int main() {
        
        struct Personnage
        {
            std::string nom;
            int age;
        };
        
        std::cout << "sizeof(Personnage) = " << sizeof(Personnage) << "\n";
        std::cout << "alignof(Personnage) = " << alignof(Personnage) << std::endl;
        return 0;
    }

     Affichage en console :

    sizeof(Personnage) = 32
    alignof(Personnage) = 8

    D'après ce code, la contrainte d'alignement de Personnage est de 8 octets alors que sa taille est de 32 octets... Je ne vois pas comment c'est possible.

    On est d'accord que la contrainte d'alignement représente bien le nombre d'octets entre 2 adresses d'objets de même type ?

    Je pensais que j'aurais le plus petit nombre au-dessus de la taille de mon objet à être une puissance de 2 (ici 32) mais ce n'est pas le cas...

    -
    Edité par Autechre 23 avril 2022 à 17:38:10

    • Partager sur Facebook
    • Partager sur Twitter
      23 avril 2022 à 17:55:25

      L'alignement est une sorte de casier avec des boîtes de taille donnée. Dans ton exemple 8. La contrainte d'alignement fait juste en sorte de mettre un objet dans chaque boîte, c'est donc n'importe quel multiple de l'alignement qu'il faut prendre en compte.

      Tu peux afficher les alignements fait par clang avec -Wpadding. (Je sais pas pour GCC).

      EDIT: je n'ai pas les mêmes chiffres que toi, mais pour l'exemple :

      sizeof(std::string) = 32
      sizeof(int) = 4
      sizeof(Personnage) = 40
      alignof(Personnage) = 8

      Ce qui fait que la structure alignée est :

      struct Personnage
      {
          std::string nom; // 32
          int age;         // +4
          char unused[4];  // +4 pour arriver a un multiple de 8
      };

      -
      Edité par gbdivers 23 avril 2022 à 17:57:49

      • Partager sur Facebook
      • Partager sur Twitter
        23 avril 2022 à 18:17:03

        Tu veux dire que la contrainte d'alignement est juste un diviseur de l'adresse d'une variable ? Ah ok... moi je n'avais pas compris ça comme ça.

        Ici : https://en.cppreference.com/w/c/language/object#Alignment

        la contrainte d'alignement est définie comme suit : "the number of bytes between successive addresses at which objects of this type can be allocated".

        Du coup moi je pensais que :

        • la taille d'un objet c'était la taille de tous ces éléments
        • la contrainte d'alignement c'était la taille de tous ces éléments + le padding

        alors que rien à voir on dirait :lol:

        • Partager sur Facebook
        • Partager sur Twitter
          23 avril 2022 à 18:20:53

          Le padding, c'est juste un moyen pour respecter la contrainte d'alignement entre 2 objets Personnage. Et cela fait partie de la taille de l'objet.
          • Partager sur Facebook
          • Partager sur Twitter
            23 avril 2022 à 18:40:27

            L'alignement c'est une contrainte qui vient du processeur. Il ne peut accéder aux types qu'il connait (les types de base en C++) qu'à certaines adresses.
            Et on a presque toujours pour ces types : alignement égale taille de l'objet. Par exemple, si un int est de taille 4 octets, son adresse doit être multiple de 4. Et l'alignement est toujours une puissance de 2.

            Quand on définit une structure, tous les champs qui la constituent doivent être alignés. Le compilateur s'occupe de gérer cela, il ajoute du padding si nécessaire. Avec un peu de recul, on voit que pour garantir cela la structure doit avoir un alignement égal à celui de champ qui a le plus grand alignement.
            Si on veut faire un tableau de structures, elles sont donc les unes à côté des autres et doivent être alignées pour garantir que leurs champs le soient aussi. Donc la taille de la structure doit être un multiple de son alignement. C'est le pourquoi du padding à la fin dans l'exemple de gbdivers.

            Exemple:

            struct  Truc {
                 bool  actif;    // taille 1 alignement aucun (=1)
                 int  nombre;    // taille 4 alignement 4
                 char  lettre;   // taille 1 alignement aucun (=1)
            };

            Si l'int fait 4 octets, cette structure a un alignement de 4 et une taille de 12 octets! Vois-tu où il y a eu du padding? En changeant l'ordre des membres, la taille de la structure descend à 8 octets:

            struct  Machin {
                 int  nombre;
                 char  lettre;
                 bool  actif;
            };
            • Partager sur Facebook
            • Partager sur Twitter

            En recherche d'emploi.

              23 avril 2022 à 21:12:56

              En gros, la contrainte d'alignement fait toujours la même taille que le plus gros type primitif de cette structure (dans ton exemple int).

              Et c'est dû au fait que le processeur ne traite pas directement la structure mais séparément les champs à l'intérieur.

              Du coup la plupart du temps la contrainte d'alignement sera 8 octets vu que les types primitifs les gros en C++ font 8 octets.

              • Partager sur Facebook
              • Partager sur Twitter

              Taille d'un objet ≥ sa contrainte d'alignement ?

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown