T est un pointeur et un pointeur n'est jamais qu'une variable numérique entière (généralement) non signée dont la taille est au minimum suffisante pour représenter l'ensemble des adresses mémoire accessibles sur le système.
Et cette taille est clairement connue à la compilation!
On se fout pas mal de savoir que l'adresse mémoire obtenue donne accès à 5, 10 ou 10000 éléments parce que chacun de ces élément est accessible à une adresse mémoire qui lui est propre et que le processeur est tout à fait en mesure de calculer sur la base de l'adresse du premier élément, de la taille des éléments et de l'indice de l'élément auquel on veut accéder.
il y a au maximum trois inconnues au moment de la compilation:
Mais cela ne pose strictement aucun problème: on sait que nous obtiendrons de toutes manière une valeur numérique entière non signée (dont la taille est parfaitement connue) correspondant à l'adresse à laquelle nous trouverons un espace contigu suffisant pour représenter l'ensemble des (to) éléments pour lesquels on a demandé de réserver de la mémoire.
- L'adresse à laquelle se trouvera le premier élément
- le nombre d'élément pour lequel l'allocation dynamique demandera de réserver de la mémoire
- l'indice de l'élément auquel on essayera d'accéder par la suite
Et nous avons la certitude que, le compilateur sachant parfaitement la taille que représente un élément en mémoire, il nous permettra d'accéder à l'ensemble des adresses mémoires auxquelles se trouve le premier byte de chaque élément.
Après, il peut y avoir certains problème:
- Le système peut ne pas trouver assez d'espace libre pour réserver l'espace pour le nombre d'éléments demandé : new va alors lancer une exception de type std::bad_alloc (ou, si on utilise la version nothrow, renvoyer l'adresse correspondant à NULL / nullptr (c++11) pour indiquer que ce n'est pas une adresse valide)
- en ayant demandé d'allouer (to) éléments, on peut essayer d'accéder à l'élément (to)+1 dont l'adresse mémoire peut contenir strictement tout et n'importe quoi. Mais ça, c'est un problème de logique, et ca n'a rien à voir avec l'alignement des données
- d'autres problèmes similaires que j'oublie peut être
L'intérêt est tout simple : une classe utilise des données pour fournir les services que l'on en attend.sur une classe, en expliquant l'intérêt. Parce que j'ai beau chercher, je n'en trouve pas.
A ce titre, il faut que le processeur soit en mesure d'accéder à ces données, au même titre qu'il doit pouvoir accéder aux différents champs d'une structure ou à n'importe quelle variable de n'importe quel type.
Seulement, si la donnée en question ne se trouve pas dans un des accumulateur du processeur (et bien qu'il y ai de plus en plus d'accumulateurs, il n'y en a pas un nombre extensible à l'infini), il va devoir aller la chercher "quelque part".
Ce "quelque part", correspond à la mémoire: soit une mémoire interne au processeur que l'on appelle "la pile", soit la mémoire générale du système qu'on appelle "le tas".
Pour pouvoir trouver "la donnée qui l'intéresse", il a donc besoin de savoir "où elle se trouve" en mémoire.
Le seul moyen qu'il ait de savoir où la données se trouve passe... par l'adresse mémoire de l'élément en question.
Et cette adresse doit etre accessible au compilateur.
Or, si les accumulateurs sont en mesure de contenir 32 ou 64 bits de données, les adresses accessibles sont toutes séparées par 32 ou 64 bits de données.
Le processeur ne peut accéder au "subdivision" de ces 32 (ou 64) bits qu'une fois que ces 32 (ou 64) bits sont chargés dans un accumulateur (parce que l'accumulateur est, lui-même subdivisé en différentes parties de 8, 16 et éventuellement 32 bits))
si tu ne précise rien et que tu crées une structure proche de
le processeur chercher l'adresse à laquelle commence la structure et qui correspondra à l'adresse de c.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 struct MyStruct{ char c; int i; };
pour que le processeur puisse accéder à i, il devra prendre l'adresse (accessible!) qui suit l'adresse de c et, au final, alors qu'un char a une taille de 1 et qu'il aurait donc suffit de 5 bytes pour représenter les deux données, tu te retrouves avec un strcuture ayant une taille de 8, "simplement" parce que le compilateur a rajouté la taille de 3 char 'de bourrage" afin de placer i à une distance qui permette au compilateur d'y accéder.
Ca, c'est ce qu'on appelle l'alignement.
Maintenant, que ce soit une structure ou une classe ne changera rien parce que le processeur devra toujours, à un moment ou à un autre, être en mesure d'accéder aussi bien à i qu'à c.
Il ne faut pas chercher un intérêt quelconque à cela, il faut y voir une obligation propre au style de fonctionnement du processeur!
C'est parce que le processeur a un mode de fonctionnement qui lui empêche d'accéder "facilement" à des données qui ne sont pas séparées par 32 (ou 64) bits que le compilateur s'arrange pour que chaque donnée de type différent se retrouve à une adresse qui sera accessible par le processeur!
Mais, pardon, tu demandes quel serait l'intérêt de modifier la manière dont les données d'une classe seraient alignées
Ce serait exactement le même que celui que tu aurais à modifier la manière dont les données d'une structure sont alignées : "grignoter" quelque bytes en espace mémoire nécessaire.
Je n'y ai personnellement jamais eu recours, mais comme on peut parfaitement utiliser C++ en embarqué et / ou pour programmer des eeprom et/ou des systèmes où le moindre byte de mémoire est important, les occasions de modifier la manière dont les données d'une classe sont alignée sont au moins aussi nombreuses que celle de le faire en C sur pour les structures.
Par contre, l'intérêt de le faire avec des données privées est, bien sur, d'en faciliter l'encapsulation
Sauf que la norme est la seule chose qui te permette d'obtenir un résultat pour lequel tu puisse espérer une portabilité totale.Certes il y a la norme C++, et il y a aussi l'utilisation de cette norme.
Le fait de jouer avec la manière dont les données sont alignées te fais prendre de très gros risques à ce niveauNuance: les développeurs C utilisent que l'alignement de structures. Les pauvres, il n'ont pas d'autre choixLes développeurs n'utilisent que l'alignement de structures (jusqu'à ce que vous me prouviez le contraire, bien sûr). Cela devient comme une norme implicite.
Les développeurs C++ peuvent parfaitement (pour des raisons qui leur sont propres, entre autre de mémoire disponible) utiliser l'alignement sur des classes.
Et, surtout, les développeur C++ qui ont le choix utiliseront l'alignement "par défaut" des données
Non!!! on peut le faire sur tout, même sur une union si tu le souhaites!On aligne des structures, et non pas des classes. Et c'est bien une différence d'utilisation entre une classe et une structure en C++. Seule chose que j'ai voulu souligner.
Ce n'est pas parce qu'il n'est pas courent de le faire (qu'il s'agisse d'une classe ou d'une structure, je n'ai personnellement jamais éprouvé le besoin de "jouer" avec l'alignement des données... et je suis sur que beaucoup de développeurs C++ qui ne travaillent pas dans l'embarqué sont dans mon cas
) que cela ne se fait pas.
C'est "simplement" que le besoin est souvent "moins présent"![]()
Mais c'est une erreur de taille!!!PS: j'ai dit qu'on ne pouvait pas aligner des classes, c'étatit une erreur en effet, mais que j'ai corrigé lorsque j'ai donné le code qui compile un alignement de classe. Cela ne change pas le raisonnement qu'on utilise des structures pour l'alignement.
Parce que tu avais commencé par dire qu'on ne pouvait pas aligner une classe, ce qui est faux.
Et, en plus, tu présentais cela comme une différence entre les classes et les structures.
Mais comme ton assertion (on ne peut pas aligner des classes) était fausse, on peut difficilement dire qu'il s'agisse d'une différence entre les deux
Du coup, on en revient strictement à la norme : la seule différence qui existe entre une classe et une structure en C++, c'est l'accessibilité par défaut qui est appliquée par le compilateur![]()
Partager