Que signifient les parenthèses dans une déclaration de variable C?

Quelqu’un peut-il expliquer ce que cela signifie?

int (*data[2])[2]; 

A quoi servent les parenthèses?

En C, les crochets [] ont une priorité plus élevée que l’astérisque *

Bonne explication de Wikipedia:

Pour déclarer une variable en tant que pointeur sur un tableau, nous devons utiliser des parenthèses. En effet, les parenthèses en C ([]) ont une priorité supérieure à l’astérisque (*). Donc, si nous souhaitons déclarer un pointeur sur un tableau, nous devons fournir des parenthèses pour remplacer ceci:

 double (*elephant)[20]; 

Cela déclare que l’éléphant est un pointeur et le type qu’il pointe est un tableau de 20 valeurs doubles.

Pour déclarer un pointeur sur un tableau de pointeurs, combinez simplement les notations.

 int *(*crocodile)[15]; 

Source

Et votre cas actuel:

 int (*data[2])[5]; 

data est un tableau de 2 éléments. Chaque élément contient un pointeur sur un tableau de 5 ints.

Donc vous pourriez avoir dans le code en utilisant votre type ‘data’:

 int (*data[2])[5]; int x1[5]; data[0] = &x1; data[1] = &x1; data[2] = &x1;//<--- out of bounds, crash data has no 3rd element int y1[10]; data[0] = &y1;//<--- compiling error, each element of data must point to an int[5] not an int[10] 

Il existe un programme très cool appelé “cdecl” que vous pouvez télécharger pour Linux / Unix et probablement aussi pour Windows. Vous collez une déclaration de variable C (ou C ++ si vous utilisez c ++ décl) et vous la formulez en mots simples.

Si vous savez lire des expressions en C, vous êtes sur le sharepoint lire des déclarations compliquées.

Qu’est-ce que

 char *p; 

Vraiment méchant? Cela signifie que *p est un caractère. Qu’est-ce que

 int (*data[2])[5]; 

signifier? Cela signifie que (*data[x])[y] est un entier (à condition que 0 <= x <2 et 0 <= y <5). Maintenant, réfléchissez à ce que cela implique. data doivent être … un tableau de 2 … pointeurs … sur des tableaux de 5 … nombres entiers.

Ne pensez-vous pas que c’est assez élégant? Tout ce que vous faites, c’est énoncer le type d’une expression. Une fois que vous aurez compris cela, les déclarations ne vous intimideront plus jamais!

La “règle rapide” consiste à commencer par le nom de la variable, balayer vers la droite jusqu’à ce que vous appuyiez sur a), revenir au nom de la variable et balayer vers la gauche jusqu’à ce que vous frappiez un (. Puis “sortez” de la paire de parenthèses et répétez le processus.

Appliquons-le à quelque chose de ridicule:

 void **(*(*weird)[6])(char, int); 

weird est un pointeur sur un tableau de 6 pointeurs vers des fonctions acceptant chacune un caractère et un int comme argument, et renvoyant chacun un pointeur vers un pointeur à void.

Maintenant que vous savez ce que c’est et comment ça se passe … ne le faites pas . Utilisez typedefs pour diviser vos déclarations en morceaux plus faciles à gérer. Par exemple

 typedef void **(*sillyFunction)(char, int); sillyFunction (*weird)[6]; 

data [2] – un tableau de deux entiers

* data [2] – un pointeur sur un tableau de deux entiers

(* données [2]) – ”

(* data [2]) [2] – un tableau de 2 pointeurs sur des tableaux de deux entiers.

Si vous avez un tableau:

 int myArray[5]; int * myArrayPtr = myArray; 

Serait parfaitement raisonnable. myArray sans les crochets est un pointeur sur un int . Lorsque vous ajoutez les crochets, c’est comme si vous respectiez le pointeur myArray . Tu pourrais écrire …

 myArrayPtr[1] = 3; 

Ce qui est parfaitement raisonnable. L’utilisation de parenthèses ne fait que rendre les choses plus difficiles à lire et à comprendre à l’OMI. Et ils montrent que les gens ne comprennent pas les pointeurs, les tableaux et l’arithmétique de pointeur, ce qui explique comment le compilateur ou l’éditeur de liens passe de l’un à l’autre. Il semble qu’avec les parenthèses, la vérification des limites soit vérifiée.