Déclaration de pointeur C pour pointer vers une ligne d’un tableau à deux dimensions

Je suis tombé sur cette déclaration dans le livre de KN King à la page 269

int a[ROWS][COLS], (*p)[COLS]; p = &a[0]; 

p pointe maintenant vers la première ligne du tableau 2-d. Je comprends pourquoi a[0] pointe vers la première ligne d’un tableau à deux dimensions. Mais je ne comprends pas la syntaxe pour déclarer p . Qu’est-ce que cela signifie et comment puis-je m’en souvenir?

Que font les parens autour de *p ? (*p) que signifie cette syntaxe en termes de priorité des opérateurs?

> "But I do not understand the syntax for declaring p"

Donc p est déclaré comme:

 int (*p)[COLS]; 

C’est un pointeur sur un tableau d’ COLS taille est COLS .

> "What does that mean and how do I remember it?"

Voici comment vous pouvez savoir, utilisez la règle de la spirale et commencez par travailler dans le () s () :

  ( p) p (*p) p is a pointer (*p)[ ] p is a pointer to an array int (*p)[ ] p is a pointer to an array of ints int (*p)[COLS] p is a pointer to an array of ints of size COLS 

Bien sûr, vous pouvez toujours sortingcher pour obtenir la réponse aussi :

entrez la description de l'image ici

> "what does this syntax mean in terms of operator precedence?"

Dans le langage C, [] a la priorité sur le unaire * , ce qui signifie que vous avez besoin de () pour que p soit un pointeur sur un tableau d’ int s, au lieu d’un tableau de pointeurs sur int s.

Les opérateurs postfix [] et () ont une priorité plus élevée que l’opérateur unaire * , ils se lient donc en premier. IOW, T *p[N] est interprété comme T *(p[N]) ; p est un tableau de pointeurs sur T Pour déclarer un pointeur sur un tableau (ou un pointeur sur une fonction), vous devez utiliser des parenthèses pour forcer l’opérateur * à se lier avant le [] :

 T *p[N]; // p is an array of pointer to T T (*p)[N]; // p is a pointer to an array of T T *f(); // f is a function returning pointer to T T (*f)(); // f is a pointer to a function returning T 

ignorer la virgule et ré-écrire comme suit:

 int a[ROWS][COLS]; int (*p)[COLS]; p = &a[0]; 

p est un pointeur sur un tableau d’ints COLS La déclaration n’alloue pas autant de mémoire, mais permet une vérification des limites. La mémoire pour le tableau a été allouée dans la déclaration de:
a => int a[ROWS][COLS];

Je comprends pourquoi un [0] pointe sur la première ligne d’un tableau à deux dimensions

C’est déjà inexact. Dans le contexte de valeur, a[0] ne pointe pas vraiment “vers la première ligne d’un tableau 2D”. a[0] pointe en fait sur le premier élément de la première ligne du tableau 2D. En d’autres termes, dans le contexte de valeur, a[0] est un pointeur sur a[0][0] . Le type de a[0] décroît en int * , comme vous le savez probablement. Et sizeof *a[0] est égal à sizeof(int) . Donc, cela ne pointe pas vraiment vers la ligne entière. Il pointe vers un object int unique.

Maintenant, si vous voulez vraiment pointer sur la première ligne d’un tableau 2D, c’est-à-dire pointer sur la ligne entière , vous avez besoin de &a[0] . Cela vous donnera un pointeur de type int (*)[COLS] . Notez que sizeof *&a[0] est égal à sizeof (int[COLS]) . Il s’agit donc vraiment d’un pointeur sur la première ligne d’un tableau 2D. C’est ce que vous voyez dans votre exemple.

Notez que numériquement a[0] et &a[0] (en tant que pointeurs dans un contexte de valeur) sont identiques, car ils pointent vers le même point dans la mémoire linéaire. Cependant, en ce qui concerne le type &a[0] pointe vers la ligne entière, tandis que a[0] pointe vers un seul élément.