web-dev-qa-db-fra.com

(arr + 2) équivaut à * (arr + 2). Comment?

J'étudie comment afficher des éléments d'un tableau 2D à l'aide de pointeurs. Voici le code que j'ai essayé:

#include<stdio.h>  

int main(){

    int arr[3][2] = {  

    {7, 8},
    {6,3},
    {3,4}
    };

    printf("%u\n", (arr + 2));
    printf("%u\n", *(arr + 2)); 
}

Sortie:

6487616
6487616

Je m'attends à ce que la sortie de *(arr + 2) soit 3. Comment est-ce la même chose que (arr + 2)?

8
dave

Un tableau 2D est vraiment un tableau de tableaux.

L'expression arr + 2 est de type int (*)[2], alors que *(arr + 2) est de type int [2]. Lorsque vous imprimez le premier, vous disposez d'un pointeur pour que la valeur du pointeur soit imprimée. Dans ce dernier cas, vous avez un tableau qui se décompose en un pointeur sur le premier élément. Donc, *(arr + 2) décompose en arr + 2, qui est identique à la première expression.

Pour plus de détails sur arr + 2, arr a le type int [3][2]. Lorsque vous lui ajoutez une valeur entière, il se décompose en un pointeur sur le premier membre. arr désintègre alors le type int (*)[2], et arr + 2 possède également ce type et pointe vers le sous-tableau contenant { 3, 4 }.

Notez également que les pointeurs doivent être imprimés avec le spécificateur de format %p et que le pointeur doit être converti en void *, sinon vous appelez comportement non défini . Dans ce cas, vous avez eu la "chance" qu’ils aient imprimé la même chose.

Pour obtenir le résultat de 3 attendu, vous devez déréférencer de nouveau la référence:

*(*(arr + 2))
14
dbush

arr est un tableau de tableaux de int. Sur presque toutes les utilisations, un tableau est converti en un pointeur sur son premier élément. Donc, arr est converti en un pointeur sur un tableau de int.

OK, arr est converti en un pointeur vers un tableau de int, donc (arr+2) est du même type, c’est-à-dire un pointeur vers un tableau de int.

Maintenant, *(arr+2) est la chose sur laquelle (arr+2) pointe. C'est-à-dire un tableau de int.

Maintenant, puisqu'il s'agit d'un tableau de int, il est converti en un pointeur sur son premier élément. Donc, *(arr+2) est converti en un pointeur sur int. Notez que c'est pas une int et qu'il est peu probable qu'elle soit égale à 3.

Maintenant, comment se fait-il que (arr+2) et *(arr+2) soient identiques? Ils sont un pointeur sur un tableau et un pointeur sur son premier élément. Bien que ces pointets soient de types différents, ils représentent la même adresse, car l'adresse de tout tableau est la même que l'adresse de son premier élément.

3
n.m.

arr est le pointeur sur le premier tableau du type int[2].(arr + 2) est le pointeur sur le troisième tableau de ce type.
Attendu que *(arr + 2) est le pointeur sur le premier élément du tableau (arr +2).
Les deux auront donc la même adresse puisqu'ils indiquent la même position. La seule différence est dans leur type .(arr+2) est du type int(*)[2] alors que *(arr + 2) est du type int *.

1
Ali