Par exemple:
sizeof(char*)
retourne 4. Comme le fait int*
, long long*
tout ce que je l' ai essayé. Y a-t-il des exceptions à cela?
Par exemple:
sizeof(char*)
retourne 4. Comme le fait int*
, long long*
tout ce que je l' ai essayé. Y a-t-il des exceptions à cela?
Réponses:
La garantie que vous obtenez est la suivante sizeof(char) == 1
. Il n'y a aucune autre garantie, y compris aucune garantie sizeof(int *) == sizeof(double *)
.
En pratique, les pointeurs seront de taille 2 sur un système 16 bits (si vous en trouvez un), 4 sur un système 32 bits et 8 sur un système 64 bits, mais il n'y a rien à gagner à s'appuyer sur un Taille.
Même sur une plate-forme simple x86 32 bits, vous pouvez obtenir une variété de tailles de pointeurs, essayez ceci pour un exemple:
struct A {};
struct B : virtual public A {};
struct C {};
struct D : public A, public C {};
int main()
{
cout << "A:" << sizeof(void (A::*)()) << endl;
cout << "B:" << sizeof(void (B::*)()) << endl;
cout << "D:" << sizeof(void (D::*)()) << endl;
}
Sous Visual C ++ 2008, j'obtiens 4, 12 et 8 pour les tailles de la fonction pointeurs vers membre.
Raymond Chen en a parlé ici .
Juste une autre exception à la liste déjà publiée. Sur les plates-formes 32 bits, les pointeurs peuvent prendre 6 octets et non 4 octets:
#include <stdio.h>
#include <stdlib.h>
int main() {
char far* ptr; // note that this is a far pointer
printf( "%d\n", sizeof( ptr));
return EXIT_SUCCESS;
}
Si vous compilez ce programme avec Open Watcom et l'exécutez, vous obtiendrez 6, car les pointeurs éloignés qu'il prend en charge sont constitués de valeurs de décalage 32 bits et de segments 16 bits.
si vous compilez pour une machine 64 bits, cela peut être 8.
sizeof(char*)==1
? Êtes-vous sûr? Tu ne veux pas dire size(char)==1
?
Techniquement parlant, la norme C ne garantit que sizeof (char) == 1, et le reste dépend de l'implémentation. Mais sur les architectures x86 modernes (par exemple les puces Intel / AMD), c'est assez prévisible.
Vous avez probablement entendu des processeurs décrits comme étant 16 bits, 32 bits, 64 bits, etc. Cela signifie généralement que le processeur utilise N bits pour les nombres entiers. Étant donné que les pointeurs stockent des adresses de mémoire et que les adresses de mémoire sont des entiers, cela vous indique effectivement combien de bits vont être utilisés pour les pointeurs. sizeof est généralement mesuré en octets, donc le code compilé pour les processeurs 32 bits indiquera la taille des pointeurs à 4 (32 bits / 8 bits par octet), et le code pour les processeurs 64 bits indiquera la taille des pointeurs à 8 (64 bits / 8 bits par octet). C'est de là que vient la limitation de 4 Go de RAM pour les processeurs 32 bits - si chaque adresse mémoire correspond à un octet, pour adresser plus de mémoire, vous avez besoin d'entiers supérieurs à 32 bits.
La taille du pointeur dépend essentiellement de l'architecture du système dans lequel il est implémenté. Par exemple, la taille d'un pointeur en 32 bits est de 4 octets (32 bits) et de 8 octets (64 bits) sur une machine 64 bits. Les types de bits dans une machine ne sont rien d'autre qu'une adresse mémoire, qu'elle peut avoir. Les machines 32 bits peuvent avoir un 2^32
espace d'adressage et les machines 64 bits peuvent avoir jusqu'à 2^64
des espaces d'adressage. Ainsi, un pointeur (variable qui pointe vers un emplacement mémoire) devrait pouvoir pointer vers n'importe quelle adresse mémoire ( 2^32 for 32 bit and 2^64 for 64 bit
) qu'une machine détient.
Pour cette raison, la taille d'un pointeur est de 4 octets sur une machine 32 bits et de 8 octets sur une machine 64 bits.
En plus des différences de bits 16/32/64, des choses encore plus étranges peuvent se produire.
Il y a eu des machines où sizeof (int *) sera une valeur, probablement 4 mais où sizeof (char *) est plus grande. Les machines qui adressent naturellement des mots au lieu d'octets doivent "augmenter" les pointeurs de caractères pour spécifier la partie du mot que vous voulez vraiment afin d'implémenter correctement la norme C / C ++.
Ceci est maintenant très inhabituel, car les concepteurs de matériel ont appris la valeur de l'adressabilité des octets.
void*
et char*
sont gérés par logiciel, et sont augmentés d'un décalage de 3 bits dans le mot - mais comme il n'y a pas réellement d'espace d'adressage 64 bits, le décalage est stocké dans les 3 bits de poids fort du 64 bits mot. Donc char*
, ils int*
sont de la même taille, mais ont des représentations internes différentes - et le code qui suppose que les pointeurs sont "vraiment" juste des entiers peut échouer gravement.
Les pointeurs 8 bits et 16 bits sont utilisés dans la plupart des microcontrôleurs à profil bas. Cela signifie que chaque machine à laver, micro, réfrigérateur, téléviseurs plus anciens et même voitures.
On pourrait dire que cela n'a rien à voir avec la programmation du monde réel. Mais voici un exemple réel: Arduino avec 1 à 4 à 4 Ko de RAM (selon la puce) avec des pointeurs à 2 octets.
Il est récent, bon marché, accessible à tous et mérite d'être codé.
En plus de ce que les gens ont dit sur les systèmes 64 bits (ou autre), il existe d'autres types de pointeurs que de pointeurs sur objets.
Un pointeur vers un membre peut avoir presque n'importe quelle taille, selon la façon dont il est implémenté par votre compilateur: ils ne sont pas nécessairement tous de la même taille. Essayez un pointeur sur membre d'une classe POD, puis un pointeur sur membre hérité d'une des classes de base d'une classe à plusieurs bases. Ce que c'est drôle.
D'après ce que je me souviens, il est basé sur la taille d'une adresse mémoire. Donc, sur un système avec un schéma d'adresse 32 bits, sizeof renverra 4, car cela fait 4 octets.
sizeof (unsigned int) == sizeof (signed int)
, cette exigence se trouve dans 3.9.1 / 3. « Pour chacun de la norme entier signé de types, il existe un correspondant (mais différente) standard de type entier non signé: unsigned char
, unsigned short int
, unsigned int
, unsigned long int
, et unsigned long long int
, dont chacun occupe la même quantité de stockage et présente les mêmes exigences d'alignement en tant que correspondant entier signé de type "
En général, sizeof (à peu près n'importe quoi) change lorsque vous compilez sur différentes plateformes. Sur une plate-forme 32 bits, les pointeurs ont toujours la même taille. Sur d'autres plates-formes (64 bits étant l'exemple évident), cela peut changer.
Non, la taille d'un pointeur peut varier en fonction de l'architecture. Il existe de nombreuses exceptions.
La taille du pointeur et de l'int entier est de 2 octets dans le compilateur Turbo C sur une machine Windows 32 bits.
La taille du pointeur dépend donc du compilateur. Mais généralement, la plupart des compilateurs sont implémentés pour prendre en charge une variable de pointeur de 4 octets en 32 bits et une variable de pointeur de 8 octets en machine 64 bits).
La taille du pointeur n'est donc pas la même sur toutes les machines.
La raison pour laquelle la taille de votre pointeur est de 4 octets est que vous compilez pour une architecture 32 bits. Comme l'a souligné FryGuy, sur une architecture 64 bits, vous verriez 8.
Dans Win64 (Cygwin GCC 5.4) , voyons l'exemple ci-dessous:
Tout d'abord, testez la structure suivante:
struct list_node{
int a;
list_node* prev;
list_node* next;
};
struct test_struc{
char a, b;
};
Le code de test est ci-dessous:
std::cout<<"sizeof(int): "<<sizeof(int)<<std::endl;
std::cout<<"sizeof(int*): "<<sizeof(int*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(double): "<<sizeof(double)<<std::endl;
std::cout<<"sizeof(double*): "<<sizeof(double*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(list_node): "<<sizeof(list_node)<<std::endl;
std::cout<<"sizeof(list_node*): "<<sizeof(list_node*)<<std::endl;
std::cout<<std::endl;
std::cout<<"sizeof(test_struc): "<<sizeof(test_struc)<<std::endl;
std::cout<<"sizeof(test_struc*): "<<sizeof(test_struc*)<<std::endl;
La sortie est ci-dessous:
sizeof(int): 4
sizeof(int*): 8
sizeof(double): 8
sizeof(double*): 8
sizeof(list_node): 24
sizeof(list_node*): 8
sizeof(test_struc): 2
sizeof(test_struc*): 8
Vous pouvez le voir en 64 bits, sizeof(pointer)
c'est 8
.
Un pointeur n'est qu'un conteneur pour une adresse. Sur une machine 32 bits, votre plage d'adresses est de 32 bits, donc un pointeur sera toujours de 4 octets. Sur une machine 64 bits où vous avez une plage d'adresses de 64 bits, un pointeur sera de 8 octets.
Par souci d'exhaustivité et d'intérêt historique, dans le monde 64 bits, il existait différentes conventions de plate-forme sur les tailles des types longs et longs, appelés LLP64 et LP64, principalement entre les systèmes de type Unix et Windows. Un ancien standard nommé ILP64 a également fait int = 64 bits de large.
Microsoft a maintenu LLP64 où longlong = 64 bits de large, mais longtemps resté à 32, pour un portage plus facile.
Type ILP64 LP64 LLP64
char 8 8 8
short 16 16 16
int 64 32 32
long 64 64 32
long long 64 64 64
pointer 64 64 64