Comment fonctionne sizeof avec ce déréférencement d'un pointeur sur un tableau?

9

Ici, j'ai un pointeur ptrsur un tableau arrde 4 entiers. ptrpointe vers l'ensemble du tableau. ptr[0]ou *ptrpointe vers le premier élément du tableau, donc l'ajout de 1 ptr[0]donne l'adresse du deuxième élément du tableau.

Je ne comprends pas pourquoi l'utilisation sizeof(ptr[0])donne la taille de l'ensemble du tableau, 16 octets, pas la taille uniquement du premier élément, 4 octets (comme ptr[0]pointe vers le premier élément du tableau).

int arr[4] = {0, 1, 2, 3};
int (*ptr)[4] = &arr;
printf("%zd", sizeof(ptr[0])); //output is 16
Abd-Elrahman Mohamed
la source
La deuxième ligne ne devrait-elle pas l'être int *ptr = arr;? Cela indiquerait le début (premier élément) du tableau, ce qui équivaut à &arr[0].
Andreas Wenzel
1
@AndreasWenzel La deuxième ligne ne devrait-elle pas être int *ptr = arr;? En fait non. int (*ptr)[4]crée ptrun pointeur vers un tableau complet de quatre intvaleurs. Une syntaxe de pointeur comme celle-ci est nécessaire pour allouer dynamiquement des tableaux multidimensionnels réels. Les "tableaux bidimensionnels" créés avec des malloc()boucles imbriquées et décrits à tort comme des tableaux multidimensionnels sont en réalité des tableaux 1-d de pointeurs vers plusieurs tableaux 1-d. Voir stackoverflow.com/questions/42094465/…
Andrew Henle

Réponses:

6

OP: ptr[0]pointe vers le premier élément du tableau.

Confusion de type. ptr[0]est un tableau.

ptr est un pointeur vers le tableau 4 d'int .
ptr[0], comme *ptrdéférence le pointeur sur un tableau .
sizeof(ptr[0])est la taille d'un tableau.


Avec sizeof(ptr[0]), ptr[0]n'engendre pas "une expression de type" pointeur vers type "qui pointe vers l'élément initial de l'objet tableau" conversion. (c11dr §6.3.2.1 3). Avec sizeof, ptr[0]est un tableau.

chux - Réintégrer Monica
la source
1
@ Abd-ElrahmanMohamed D'accord "Mais ptr [0] [0] est un entier qui ne pointe pas sur un entier". "ptr [0] est l'adresse du premier élément du tableau" n'est pas vrai.
chux
1
@ Abd-ElrahmanMohamed oui, les valeurs sont les mêmes mais les types sont différents. ptr [0] a un type de tableau et &ptr[0][0]a un int *type
Green Tree
1
@chux ptr[0](converti implicitement en int *) évaluerait l'adresse du premier élément int.
Green Tree
1
@chux à propos de sizeof - à droite, j'ai mal compris le contexte de ce que vous avez dit
Green Tree
1
@ Abd-ElrahmanMohamed Ce n'est pas le cas. printf("someforamt", ptr[0] , ptr[0]+1)fait quelque chose de différent de sizeof(ptr[0]). Dans ptr[0]le premier cas passe par une conversion inplicite. Avec sizeof(ptr[0]), ptr[0]non.
chux
5

ptrvoici de type pointer to an array of 4 int elementset le type de tableau a une taille 16 sur votre plateforme (sizeof (int) * (nombre d'elemetns)).

Je ne comprends pas pourquoi l'utilisation de sizeof (ptr [0]) donne à la taille du tableau entier 16 octets et non à la taille du premier élément seulement 4 octets

parce que le système de type C a des types de tableau. Ici les deux arret l' *ptra. Ce que vous déclarez avoir. Pour obtenir sizeof int ici, vous devez sizeof (ptr [0] [0]) - où ptr [0] est évalué en tableau.

Arbre vert
la source
2

avec int (*ptr)[4] = &arr ;vous avez un pointeur sur un tableau de quatre entiers et pointant sur arr.

ptrpointe maintenant vers arr, comme un double pointeur. Nous pouvons accéder à des éléments de l' arrutilisation ptr[0][x]xpourrait être 0à 4.

C'est la sizeof(ptr[0])même chose quesizeof(arr)

rsonx
la source
2

Par définition, ptr[0]est le même que celui *(ptr + 0)qui à son tour est le même que *ptr. De plus, ptrest initialisé avec &arr, *ptrest ainsi *&arret c'est juste arr. Notez que le stockage intermédiaire &arren ptrne pas effectuer une décroissance de tableau, de sorte que l'équivalence soit maintenue et aucune information de type est perdu.

Notez que tout cela est calculé au moment de la compilation, juste pour éviter cet écueil supplémentaire.

Ulrich Eckhardt
la source