1
votes

difficulté dans les pointeurs multidimensionnels en c?

J'ai un programme C qui utilise des pointeurs mais je n'arrive pas à comprendre le résultat. Pourquoi la première sortie est 1 et l'autre est 210 . Ce sont tous les deux des pointeurs vers un tableau en 3 dimensions.

Je ne suis pas en mesure de trouver une solution

int main() {    
    char arr[5][7][6];    
    char (*p)[5][7][6] = &arr;    
    printf("%d\n", (&arr + 1) - &arr);    
    printf("%d\n", (char *)(&arr + 1) - (char *)&arr);    
    printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);    
    printf("%d\n", (unsigned)(p + 1) - (unsigned)p);    
    return 0;    
}    

la première sortie est 1 et le dernier est 210


2 commentaires

À quoi vous attendiez-vous au lieu de 1 et 210 et pourquoi?


leur valeur doit être la même en premier et en deuxième car ils sont tous les deux pointeurs vers le même tableau en trois dimensions, donc la réponse pour les deux devrait être 210 naa


3 Réponses :


1
votes
(unsigned)p

0 commentaires

3
votes

C fait l'arithmétique des pointeurs en unités du type pointé.

Dans (& arr + 1) - & arr , & arr est l'adresse d'un caractère [5] [7] [6] ( un tableau de 5 tableaux de 7 tableaux de 6 char ). Ensuite, & arr +1 est l'adresse d'un caractère [5] [7] [6] au-delà de & arr et (& arr + 1 ) - & arr est la distance entre & arr et & arr + 1 mesurée en unités de char [5] [7] [6] , donc la distance est d'une unité.

Dans (char *) (& arr + 1) - (char *) & arr) , les deux adresses sont converties en char * , donc l'arithmétique se fait en unités de char . Le résultat est donc la distance entre & arr et & arr + 1 mesurée en unités de char . Puisque la distance entre & arr et & arr + 1 est d'un car [5] [7] [6] , elle est de 5 • 7 • 6 char , soit 210 char , donc le résultat est 210.

Incidents

N'utilisez pas % d pour imprimer les résultats de la soustraction de pointeurs. Lorsque deux pointeurs sont soustraits, le type du résultat est ptrdiff_t , et il peut être imprimé avec % td , comme dans printf ("% td \ n" , (& arr + 1) - & arr)); .

Pour convertir les pointeurs en nombres entiers, il est préférable d'utiliser uintptr_t , défini dans , plutôt que unsigned .

/ p>

Pour imprimer les valeurs non signées , utilisez % u et non % d .

Pour imprimer les valeurs uintptr_t , incluez et utilisez "%" PRIuPTR , comme dans printf (" % "PRIuPTR" \ n ", (uintptr_t) (p + 1) - (uintptr_t) p); .


2 commentaires

Monsieur, pouvez-vous expliquer pourquoi unsigned donne également 210.est-ce le non signé, alors ne devrait-il pas être divisé par 4. juste un peu confus


@HarshChaturvedi: Lorsqu'une adresse est convertie en un type entier tel que unsigned , la plupart des implémentations C réinterprètent simplement l'adresse mémoire comme un entier, produisant effectivement une adresse d'octet. (La norme C permet la flexibilité pour d'autres choses.) Lorsque les deux valeurs entières sont soustraites, la différence est simplement la différence en octets.



2
votes

Premièrement, il n'est pas sûr d'utiliser % d pour imprimer les différences de pointeur, qui sont de type ptrdiff_t (qui est une version signée de size_t ).

En ignorant cela, vous avez les déclarations suivantes:

(unsigned)(p + 1) - (unsigned)p)

En soustrayant deux pointeurs, le résultat est divisé par la taille de la cible (c'est-à-dire l'inverse de ce se produit lorsque vous ajoutez un entier à un pointeur, auquel cas l'entier est mis à l'échelle par la taille).

Pour le premier exemple:

(unsigned)(arr + 1) - (unsigned)arr

Ici & arr et & arr + 1 ont le type char (*) [5] [7] [6] , donc la taille de ce qu'ils pointent to est sizeof (char [5] [7] [6]) . L'addition du pointeur multiplie 1 par cette taille, et la soustraction du pointeur divise la différence par cette taille, l'annulant. Le résultat est donc 1 , quelle que soit la taille de la cible.

Pour le deuxième exemple:

(char *)(&arr + 1) - (char *)&arr

Voici l'ajout du pointeur multiplie à nouveau 1 par sizeof (char [5] [7] [6]) , qui est sizeof (char) * 5 * 7 * 6 , soit 1 * 5 * 7 * 6 qui est 210 . Mais la soustraction divise par sizeof (char) qui est 1 . Le résultat est donc 210.

Pour le troisième exemple:

(&arr + 1) - &arr

L'effet du unsigned code> casts est similaire à l'effet de char * casts dans l'exemple précédent. Cependant, dans celui-ci, deux pointeurs sont arr et arr + 1 . Dans ce contexte, les types de tableaux "se désintègrent" vers les types de pointeurs char (*) [7] [6] . La taille de la cible du pointeur est donc sizeof (char) * 7 * 6 soit 1 * 7 * 6 qui vaut 42 . Donc le résultat est 42.

Enfin, pour le dernier exemple:

char arr[5][7][6];
char (*p)[5][7][6] = &arr;

Les deux p code > et p + 1 ont le type char (*) [5] [7] [6] , donc la taille cible est 210 . Le unsigned casts à nouveau aboutit à une soustraction d'adresse directe, sans division appliquée au résultat. Le résultat est donc 210.


0 commentaires