Pour le programme:
#include int main(void) { int (*a)[2]; int b[5]; printf("sizeof(int) : %zu\n", sizeof(int)); printf("sizeof(int*) : %zu\n", sizeof(int*)); printf("sizeof(b) : %zu\n",sizeof(b)); printf("sizeof((int*)b) : %zu\n",sizeof((int*)b)); printf("sizeof(&b[0]) : %zu\n",sizeof(&b[0])); printf("sizeof(a) : %zu\n",sizeof(a)); printf("sizeof(a[0]) : %zu\n",sizeof(a[0])); printf("sizeof(a[1]) : %zu\n",sizeof(a[1])); return 0; }
La sortie est:
sizeof(int) : 4 -> Fact 1 sizeof(int*) : 8 -> Fact 2 sizeof(b) : 20 -> Case 1 sizeof((int*)b) : 8 -> Case 2 sizeof(&b[0]) : 8 -> Case 3 sizeof(a) : 8 -> Case 4 sizeof(a[0]) : 8 -> Case 5 sizeof(a[1]) : 8 -> Case 6
Questions / Observations (dans l’ordre du cas):
Le cas 1 est-il une sortie 20 parce que b
été déclaré comme un tableau d’entiers, c’est-à-dire int[]
? Le bloc total en octets est renvoyé comme confirmé par Fact1. N’est-ce pas?
Je suppose que le casting de b
to int*
fait la différence. Ici, b
est considéré comme un pointeur. Je l’ai confirmé en utilisant Fact2. Vrai ou faux?
&b[0]
se désintègre en un pointeur b
. La sortie coïncide avec Fact2.
Je m’attendais à 16 ici mais j’ai 8 comme sortie. J’ai conclu que c’est parce a
est finalement un pointeur et que la sortie coïncide avec Fact2. J’ai eu la sortie semblable à la question 2.
a[0]
est un pointeur. La sortie coïncide avec Fact2
a[1]
est un pointeur. La sortie coïncide avec Fact2
S’il vous plaît, répondez aux questions et corrigez-moi si l’une des observations est fausse.
S’il vous plaît, répondez aux questions et corrigez-moi si l’une des observations est fausse.
- Le cas 1 est-il une sortie
20
parce queb
été déclaré comme unarray
d’inters, c’est-à-direint[]
? Le bloc total en octets est renvoyé comme confirmé par Fact1. N’est-ce pas?
Oui, le résultat montre la sizeof(int [5])
. Donc de Fact1, la taille est de 5*4
- Je suppose que le casting de
b
toint*
fait la différence. Ici,b
est considéré comme un pointeur. Je l’ai confirmé en utilisant Fact2. Vrai ou faux?
Droite. Mais en ajoutant plus d’informations: sizeof
n’a besoin que du type d’expression et n’évalue pas expression (pour valeur) sauf s’il s’agit d’un type VLA. (De la section 6.5.3.4 L’opérateur sizeof des spécifications C99 )
Parce que vous appliquez le résultat final, tout ce qui va suivre n’a aucune importance.
&b[0]
se désintègre en un pointeurb
. La sortie coïncide avec Fact2.
Non et oui. Le type de b[0]
est int
et le type de &b[0]
est déjà int *
(rappelons que [...]
se lie plus étroitement que &
). Il n’y a pas de pourriture. Et oui, la sortie coïncide avec Fact2.
- Je m’attendais à 16 ici mais j’ai 8 comme sortie. J’ai conclu que c’est parce que a est finalement un pointeur et que la sortie coïncide avec Fact2. J’ai eu la sortie semblable à la question 2.
a
pointeur sur le tableau 2 de int
. Donc, la taille imprimée est de pointeur (vers un tableau int
).
int (*a)[2];
déclare a
pointeur en tant que sur le tableau 2 de int
. Donc, vous obtenez la taille du pointer to array
.
Pour obtenir le résultat souhaité (taille du tableau 2 de pointeurs sur int
), utilisez: int *a[2];
int (*a)[2]; a anonymous +----+ +----+----+ | a |----->|int |int | +----+ +----+----+ int *b[2]; b +----+----+ |int*|int*| +----+----+ b[0] b[1]
a[0]
est un pointeur. La sortie coïncide avec Fact2a[2]
est un pointeur. La sortie coïncide avec Fact2
Comme indiqué précédemment, a
est un pointeur sur le tableau 2 de int
. Donc, a[index]
est un tableau 2 si int
. Ainsi, les types de a[0]
et de a[1]
sont les tableaux 2 d’ int
. Donc, le résultat est 2*4
du fait 1.
Peut-être sans rapport avec cette réponse mais a
n’est pas initialisé et son utilisation dans une expression causerait un comportement indéfini . Bien qu’il soit bon d’utiliser dans sizeof
Pour comprendre le résultat, analysons le type d’argument de sizeof
printf("sizeof(b) : %zu\n",sizeof(b)); // int [5] printf("sizeof((int*)b) : %zu\n",sizeof((int*)b)); // int * printf("sizeof(&b[0]) : %zu\n",sizeof(&b[0])); // int * printf("sizeof(a) : %zu\n",sizeof(a)); // int (*) [2] printf("sizeof(a[0]) : %zu\n",sizeof(a[0])); // int [2] printf("sizeof(a[1]) : %zu\n",sizeof(a[1])); // int [2]
Un programme portable (non infaillible) pour confirmer les types ressemble à:
assert(sizeof(b) == sizeof(int [5])); assert(sizeof((int*)b) == sizeof(int *)); assert(sizeof(&b[0]) == sizeof(int *)); assert(sizeof(a) == sizeof(int(*)[2])); assert(sizeof(a[0]) == sizeof(int[2])); assert(sizeof(a[1]) == sizeof(int[2]));
L’opérateur sizeof
est l’un des rares éléments permettant de distinguer un tableau (en supposant qu’il ne s’agisse pas d’un paramètre de fonction) d’un pointeur.
b
est reconnu comme un tableau de 5 éléments où chacun est de 4 octets, donc sizeof(b)
évalué à 20. int
, alors bien sûr, le type est int *
. Pour répondre à l’un de vos commentaires, il n’est toujours pas exact de dire que l’expression &b[0]
se décompose en un pointeur si vous le transmettez à une fonction, car c’est en fait un pointeur, pas un tableau. a
est un pointeur sur un tableau, la taille est la taille d’un pointeur, c’est-à-dire 8. Ceci est différent de int *c[2]
, qui est un tableau de pointeurs et aurait une taille de 16. a[0]
n’est pas un pointeur mais un tableau de taille 2 . La syntaxe a[0]
est équivalente à *(a + 0)
. Donc, puisque a
est un pointeur sur un tableau, le déréférencement de a
nous donne un tableau. Puisque chaque élément est de 4 octets, la taille est de 8. Si a a
été défini comme étant int (*a)[3]
alors sizeof(a[0])
évalué à 12. a[1]
est un tableau de taille 2. Ainsi, sizeof(a[1])
évalué à 8 car il s’agit d’un tableau de 2 éléments de taille 4. Voici un exemple d’utilisation de a
:
int (*a)[2]; int d[3][2]; a=d; d[0][0]=1; d[0][1]=2; d[1][0]=3; d[1][1]=4; d[2][0]=5; d[3][1]=6; printf("a00=%d\n",a[0][0]); printf("a01=%d\n",a[0][1]); printf("a10=%d\n",a[1][0]); printf("a11=%d\n",a[1][1]); printf("a20=%d\n",a[2][0]); printf("a21=%d\n",a[3][1]);
Sortie:
a00=1 a01=2 a10=3 a11=4 a20=5 a21=6
Vous l’utilisez également lorsque vous passez un tableau 2D à une fonction:
void f(int (*a)[2]) { ... } int main() { int x[3][2]; f(x); }
Voici un peu de recherche individuelle sur le sujet. J’ai exécuté votre code de test dans quatre environnements différents, deux 64 bits et deux 32 bits.
J’ai utilisé trois compilateurs différents: llvm, gcc et mipsPro cc.
Voici la comparaison commentée des résultats :
// 64-bit environment - all comstackrs sizeof(int) : 4 -> Fact 1 -32 bit int -> 4 bytes sizeof(int*) : 8 -> Fact 2 -this and other pointers in a 64-bit system are 8-bytes long sizeof(b) : 20 -> Case 1 -array of 5 32 bit ints -> 20 bytes sizeof((int*)b) : 8 -> Case 2 sizeof(&b[0]) : 8 -> Case 3 sizeof(a) : 8 -> Case 4 sizeof(a[0]) : 8 -> Case 5 -array of two 4 byte ints sizeof(a[1]) : 8 -> Case 6 -array of two 4 byte ints // 32-bit environments - all comstackrs sizeof(int) : 4 -> Fact 1 -32 bit int -> 4 bytes sizeof(int*) : 4 -> Fact 2 -this and other pointers in a 32-bit system are 4-bytes long sizeof(b) : 20 -> Case 1 -array of 5 32 bit ints -> 20 bytes sizeof((int*)b) : 4 -> Case 2 sizeof(&b[0]) : 4 -> Case 3 sizeof(a) : 4- > Case 4 sizeof(a[0]) : 8 -> Case 5 -array of two 4 byte ints sizeof(a[1]) : 8 -> Case 6 -array of two 4 byte ints
Interprétation – tous les résultats correspondent systématiquement au modèle suivant:
int
dépendait du compilateur, et peut-être toujours, autant que je sache. Il est dans tous les environnements testés et compilateurs à 4 octets (fait 1). 2*sizeof(int)
(cas 5,6). a[0]
peut être réécrit comme *a
; a[1]
peut également être écrit comme *(a + 1)
. Le poste SO suivant le développe en détail.
J’espère que cela peut consortingbuer à votre sujet.