En lisant le livre C ++ Primer, je suis tombé sur cette déclaration: "Le nombre d'éléments dans un tableau fait partie du type du tableau." Je voulais donc savoir en utilisant le code suivant:
#include<iostream>
int main()
{
char Array1[]{'H', 'e', 'l', 'p'};
char Array2[]{'P', 'l', 'e', 'a', 's', 'e'};
std::cout<<typeid(Array1).name()<<std::endl; //prints A4_c
std::cout<<typeid(Array2).name()<<std::endl; //prints A6_c
return 0;
}
Et fait intéressant, le résultat de typeid sur les deux tableaux a montré qu'ils sont en quelque sorte différents.
- Que se passe-t-il dans les coulisses?
- Pourquoi est-il nécessaire pour les tableaux d'avoir un type qui inclut sa taille? Est-ce simplement parce que sa taille ne doit pas changer?
- Comment cela affectera-t-il la comparaison des tableaux?
Je veux juste pouvoir comprendre le concept en profondeur.
Réponses:
Un attribut non alloué dynamiquement est, par définition, un conteneur de taille fixe d'éléments homogènes. Un tableau d'
N
éléments de typeT
est disposé en mémoire sous la forme d'une séquence contiguë d'N
objets de typeT
.Je ne pense pas qu'il soit "nécessaire" pour qu'un type de tableau inclue sa taille - en fait, vous pouvez utiliser un pointeur pour faire référence à une séquence contiguë d'
T
objets. Un tel pointeur perdrait des informations de taille sur le tableau.C'est cependant une chose utile à avoir. Il améliore la sécurité des types et code des informations utiles au moment de la compilation qui peuvent être utilisées de plusieurs manières. Par exemple, vous pouvez utiliser des références à des tableaux pour surcharger des tableaux de différentes tailles
ou pour déterminer la taille d'un tableau en tant qu'expression constante
Ce n'est pas vraiment le cas.
Vous ne pouvez pas comparer des tableaux de style C de la même manière que vous compareriez deux nombres (par exemple des
int
objets). Il faudrait écrire une sorte de comparaison lexicographique et décider ce que cela signifie pour des collections de différentes tailles.std::vector<T>
prévoit que , et la même logique peut être appliquée aux tableaux.Bonus: C ++ 11 et supérieur fournit
std::array
, qui est un wrapper autour d'un tableau de style C avec une interface de type conteneur. Il doit être préféré aux tableaux de style C car il est plus cohérent avec d'autres conteneurs (par exemplestd::vector<T>
) et prend également en charge les comparaisons lexicographiques hors de la boîte.la source
std::equal
(viastd::begin
etstd::end
qui sont définis pour les tableaux). Dans ce cas, des tableaux de tailles différentes ne sont pas égaux.La quantité d'espace allouée à un objet lorsque vous le créez dépend entièrement de son type. L'allocation dont je parle n'est pas des allocations de
new
oumalloc
, mais l'espace qui est alloué pour que vous puissiez exécuter votre constructeur et initialiser votre objet.Si vous avez une structure définie comme (par exemple)
Ensuite, lorsque vous construisez l'objet:
Vous pouvez considérer le processus de construction de l'objet comme un processus:
'a'
et'b'
vers l'objet)Il est important de noter que les 2 octets d'espace nécessaires sont entièrement déterminés par le type de l'objet, les arguments de la fonction n'ont pas d'importance. Ainsi, pour un tableau, le processus est le même, sauf que maintenant la quantité d'espace nécessaire dépend du nombre d'éléments dans le tableau.
Donc, les types de
a
etb
doivent refléter le fait qu'il aa
besoin de suffisamment d'espace pour 1 caractère et qu'ilb
faut suffisamment d'espace pour 5 caractères. Cela signifie que la taille de ces tableaux ne peut pas changer soudainement, une fois qu'un tableau à 5 éléments est créé, il s'agit toujours d'un tableau à 5 éléments. Afin d'avoir des objets de type "tableau" dont la taille peut varier, vous avez besoin d'une allocation de mémoire dynamique, que votre livre devrait couvrir à un moment donné.la source
C'est pour une raison interne à la bibliothèque d'exécution. Si vous considérez les déclarations suivantes, par exemple:
Ensuite, il devient clair quel est le problème: par exemple, l'adressage de
unsigned int *
doit se préoccuper de l'sizeof operator
adressage deunsigned int
.Il y a une explication plus détaillée pour le reste de ce que vous voyez ici, mais c'est en grande partie une récapitulation de ce qui a été couvert dans le langage de programmation C, 2e édition par Kernighan et Ritchie concernant le programme qui imprime le texte en langage clair du type déclaré chaîne.
la source