web-dev-qa-db-fra.com

Le sizeof (un pointeur) est-il toujours égal à quatre?

Par exemple: sizeof(char*) renvoie 4. De même que int*, long long*, tout ce que j'ai essayé. Y a-t-il des exceptions à cela?

214
Joel

La garantie que vous obtenez est que sizeof(char) == 1. Il n'y a aucune autre garantie, y compris aucune garantie que sizeof(int *) == sizeof(double *).

En pratique, les pointeurs sont de taille 2 sur un système 16 bits (si vous en trouvez un), de 4 sur un système 32 bits et de 8 sur un système 64 bits, mais rien ne sert de gagner à compter sur un Taille.

180
David Thornley

Même sur une plate-forme x86 32 bits standard, vous pouvez obtenir une variété de tailles de pointeur. 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, je reçois 4, 12 et 8 pour les tailles de la fonction pointeur-membre.

Raymond Chen en a parlé ici .

36
Eclipse

Juste une autre exception à la liste déjà affichée. Sur les plates-formes 32 bits, les pointeurs peuvent prendre 6, 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 distants qu'il prend en charge sont constitués d'un décalage 32 bits et de valeurs de segment 16 bits.

29
dmityugov

si vous compilez pour un ordinateur 64 bits, il est possible que ce soit 8.

24
FryGuy

Techniquement parlant, la norme C ne garantit que que sizeof (char) == 1, et le reste dépend de la mise en œuvre. Mais sur les architectures x86 modernes (par exemple, les puces Intel/AMD), cela est assez prévisible.

Vous avez probablement entendu parler de 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 entiers. Étant donné que les pointeurs stockent des adresses de mémoire et que celles-ci sont des entiers, cela vous indique combien de bits vont être utilisés pour les pointeurs. sizeof est généralement mesuré en octets; le code compilé pour les processeurs 32 bits indique donc une taille de 4 pointeurs (32 bits/8 bits par octet) et le code pour les processeurs 64 bits indique une taille de 8 pointeurs. (64 bits/8 bits par octet). C’est d’où 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.

17
Joseph Garvin

En plus des différences de 16/32/64 bits, des événements 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 grand. Les machines qui s'adressent naturellement à des mots au lieu d'octets doivent "augmenter" les pointeurs de caractère pour spécifier la partie du mot que vous voulez réellement afin de mettre en œuvre 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.

6
Darron

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) dans une machine 64 bits. Les types de bits d'une machine ne sont rien d'autre qu'une adresse mémoire, qu'elle peut avoir. Les machines 32 bits peuvent avoir 2^32 l'espace d'adressage et les machines 64 bits peuvent avoir jusqu'à 2^64 espaces d'adressage. Ainsi, un pointeur (variable qui pointe vers un emplacement de mémoire) devrait pouvoir pointer sur n’importe quelle adresse de mémoire (2^32 for 32 bit and 2^64 for 64 bit) qu’une machine 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.

6
Rndp13

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-ondes, réfrigérateur, télévisions plus anciennes et même les voitures.

Vous pouvez dire que cela n'a rien à voir avec la programmation du monde réel. Mais voici un exemple concret: Arduino avec une RAM 1-2-4k (selon la puce) avec des pointeurs sur 2 octets.

Il est récent, bon marché, accessible à tous et mérite d’être codé.

5
Kobor42

Outre ce que les gens ont dit à propos des systèmes 64 bits (ou autre), il existe d'autres types de pointeur que le pointeur sur l'objet.

Un pointeur sur un membre peut avoir presque n'importe quelle taille, selon la manière dont il est implémenté par votre compilateur: ils ne sont même pas nécessairement tous de la même taille. Essayez un pointeur vers un membre d'une classe POD, puis un pointeur vers un membre hérité de l'une des classes de base d'une classe à plusieurs bases. Ce que c'est drôle.

4
Steve Jessop

De ce que je me souviens, c'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, puisque c’est 4 octets.

3
Will Mc

En général, sizeof (à peu près n'importe quoi) va changer 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 (l'exemple 64 bits étant évident), cela peut changer.

3
Sean Reilly

Non, la taille d'un pointeur peut varier en fonction de l'architecture. Il y a de nombreuses exceptions.

3
Judge Maygarden

La taille du pointeur et de l'int est de 2 octets dans le compilateur Turbo C sur une machine Windows 32 bits.

Donc, la taille du pointeur est spécifique au 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 dans toutes les machines.

3
finalsemester.co.in

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 voir qu'en 64 bits, sizeof(pointer) est 8.

2
Jayhello

Si la taille de votre pointeur est de 4 octets, c'est parce que vous compilez pour une architecture 32 bits. Comme FryGuy l'a souligné, sur une architecture 64 bits, vous verriez 8.

1
Will Bickford

Un pointeur est juste un conteneur pour une adresse. Sur une machine 32 bits, votre plage d'adresses est de 32 bits. Un pointeur sera donc toujours 4 octets. Sur une machine 64 bits où vous avez une plage d'adresses de 64 bits, un pointeur sera de 8 octets.

1
Ed S.

Par souci d’intégralité et d’intérêt historique, dans le monde 64 bits, il existait différentes conventions de plate-forme sur la taille des types long et long, nommés LLP64 et LP64, principalement entre les systèmes de type Unix et Windows. Une ancienne norme appelée ILP64, également faite int = 64-bit wide.

Microsoft maintenait LLP64 où longlong = 64 bits, mais restait longtemps à 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

Source: https://stackoverflow.com/a/384672/48026

0
Hernán