9
votes

Est INT * TRAY [32] un pointeur à une matrice de 32 INTS, ou un tableau de 32 pointeurs vers INT? Est-ce que ça importe?

Si j'écris

int *columns[32];


0 commentaires

8 Réponses :


16
votes

En cas de doute - Demandez CDECL CODE>

$> cdecl 
Type `help' or `?' for help
cdecl> explain int *columns[32]
declare columns as array 32 of pointer to int


6 commentaires

Par curiosité, savez-vous où obtenir CDECL ? Les cochons capitalistes de Apple n'étaient pas assez gentils pour en fournir un avec leurs outils de développeur.


@Chris Mac OS X n'inclut pas CDECL? Je pensais que c'est un outil standard pour tous les UNIXES. Vous pouvez saisir la source CDECL de n'importe quelle distribution Linux et la compiler sur Mac OS X - Je ne pense pas que cela ait des dépendances (bien, peut-être readline)


Ce serait très utile, si le lien vers la page de téléchargement CDECL a été ajouté. Bonus si cela inclut également Windows Télécharger ... :)


@Chris: Ce n'est pas non plus dans Macports ni en fins. On dirait que vous devrez le compiler à la main.


@Stefano - Fait ça. C'est plutôt difficile. Je devais pirater un peu pour le faire travailler, mais maintenant ça marche. Pour toute personne intéressée, je l'ai eu de packages.debian.org/sid/devel/cdecl Mais cela n'a pas fonctionné hors de la boîte (ou même après avoir été patché). Tout ce que je devais faire était de commenter quelques lignes et compilé.


@QRDL: Il existe également une version de CDECL Online for Public Use: CDECL.ORG



0
votes

Un programme de test est illustratif, en particulier à ceux d'entre nous qui ne sont pas des avocats de langue: xxx

Il semble être un tableau de pointeurs.


5 commentaires

Je dirais à peine que la compréhension des déclarations nécessite le statut de «avocat de langue».


Je sais, mais je ne pouvais jamais me souvenir de lequel c'était non plus, et OS X n'a ​​pas de jolie version de CDECL installé.


La plupart des non-avocats ne pourraient pas vous dire ce que void (* (* (* (* p) [n] [m]) [O]) (char c) = 0; déclare sans utiliser CDECL ou Geordi ou d'autres astuces, je pense.


En fait, il existe une procédure simple pour briser les déclarations velues, mais les restrictions sur le champ de commentaire rendent difficile la démontration. Simplement parler, trouvez l'identifiant le plus à gauche et travaillez votre issue, en vous rappelant que [] et () lier avant *. Donc, vous commencez avec P, puis notez que c'est un pointeur (* p) à un tableau N-Element (* p) [n] de m-element étaux (* p) [n] [m] des pointeurs (* (* p) [n] [m] [m]) à des tableaux d'éléments O-ols (* (* (* (* (* (* (* (* ) [N] [m]) [O] des pointeurs (* (* (* p) [n] [m]) [O]) Pour les fonctions prenant un charme code> (* (* (* (* p) [n] [m]) [O]) (char c) et retourner vide void (* (* (* (* (* (N] [n] ) [O]) (char c)


@John, bien sûr, tout est facile à la fin. J'applique personnellement la règle "à droite puis à gauche", qui fonctionne aussi simple: p est un ") -> gauche" < Pointeur sur "(-> droite " matrice de n tableaux de m ") -> gauche "< Pointeur sur " (-> droite " tableau de O ") -> gauche " pointeur à " (-> droite " Fonction prise de char " EOL -> gauche "< et retourner vide . mais Vous devez d'abord connaître ces règles et comment ils interagissent avec les précédents, etc. Donc, je pense que la plupart des non-avocats sont perdus dans cet enfer de parenthèses.



7
votes

Vous définissez un tableau de 32 pointes.

Pour définir un pointeur à un tableau de 32 INTS, vous devez faire P>

int myintegers[32] = {0, 1, 2, ..., 31};
int (*columns)[32];

columns = &myintegers;

printf("%d\n", (*columns)[2]);


0 commentaires

5
votes

Il s'agit d'un tableau de 32 pointeurs à int et oui, ça compte.

Les règles de grammaire C Spécifiez que l'accès au tableau ( [] ) se lie plus serré que la déséroférence ( * ) et des déclarations d'utilisation de miroir.

La déclaration int * colonnes [32]; signifie que l'expression * colonnes [n] (où n est un nombre compris entre 0 et 31) est un int . Cette expression est la même que * (colonnes [n]) . La Déclaration alloue l'espace pour 32 pointes, mais il n'y a aucun int s alloué et (en supposant qu'il s'agisse d'une déclaration locale de fonction) Aucun des pointeurs n'est initialisé.

avait été la déclaration int (* colonnes) [32]; alors l'expression (* colonnes) [n] aurait été un int , ce qui signifie que le * Drérerefence se produit avant l'accès au tableau, les colonnes auraient donc été un pointeur sur un tableau de 32 int s. La déclaration aurait alloué un pointeur, mais aucun tableau de int s.


7 commentaires

Je ne suis pas une grande partie d'un utilisateur C / C ++, mais la langue m'intéresse. Cela semble un peu contre-intuitif, peut-être parce que je viens d'un contexte C #. Si vous déclarez INT (* colonnes) [32], je m'attendrais à obtenir un tableau de 32 pointes. Je per t-je de manière à ce que l'expression de la parenthèse spécifie un type de pointeur et que le spécificateur de tableau signifie "32 instances du type à gauche". Ainsi - 32 pointeurs. La même chose va dans l'autre sens - si vous dites des colonnes INT * [32] et que les crochets se lient plus fort, la manière intuitive est une matrice de 32 éléments, puis un pointeur à celui-ci.


Pourquoi est-ce l'inverse? J'ai également vu des parenthèses-syntaxe dans d'autres endroits, notamment des pointeurs de fonction. Et cela n'a pas de sens pour moi là non plus. Comment devrais-je y penser pour que cela ait un sens?


Les K & R sont probablement plus adaptés à la réponse à «pourquoi». :) Je suis d'accord avec votre intuition, cependant.


La raison est que les déclarations C suivent la «règle d'utilisation des matchs de déclaration». Cela signifie que int * x est destiné à être lu * x est un int . C'est juste une solution que la langue aurait pu être décrite. Je trouve que cela aide vraiment quand vous avez des matrices 2D. Si vous avez int x [2] [4] , cela signifie que x [0] [3] [3] est un int . Devoir inverser les limites d'index entre la déclaration et l'utilisation aurait conduit à une sorte de confusion différente.


La clé pour comprendre comment lire toutes les déclarations C complexes C est bien décrite ici par Charles. Tout commence par la lecture int * x; comme " * x est un int ", pas " x est un int * ". Appliquez tous les "opérateurs" à l'étiquette dans l'ordre normal et vous vous retrouvez avec le type de base donné.


Cela devrait être la réponse acceptée IMHO. Pourquoi le CDCL a-t-il été accepté? Il ne contient aucune sorte d'explication ...


@Vilx - Élargir sur la discussion "DÉCLARATION D'UTILISATION" ci-dessus, si vous avez une gamme de pointeurs à int et vous souhaitez accéder à une valeur INT, vous utiliseriez l'expression * a [i] ; IOW, vous trouvez l'élément de ranger, puis la déréence. Inversement, si vous utilisiez un pointeur sur un tableau, vous devez d'abord le pointeur, puis trouver le bon élément de tableau; I.e., (* a) [i] . Cette structure est reflétée dans la déclaration.



0
votes

Voici quelques déclarations amusantes pour vous:

int *arrayOfIntP[32];
int (*pointerToArrayOf32)[32];


0 commentaires

0
votes

Un astuce est de lire de droite à gauche.

donné Int * cols [32];

  1. Vous voyez d'abord les cols [32]: Ceci est une matrice de taille 32.
  2. Ensuite, VOUS VOIRES INT *: Ceci est un pointeur

    Tout ce qui reste de la matrice est le type des éléments de la matrice. Nous l'avons donc lu sous la forme d'un éventail de pointeurs à int (et de compte 32).


0 commentaires

21
votes

Élargir sur un commentaire à une autre réponse:

Il existe une procédure assez simple pour la lecture des déclarations C. Commencez par l'identifiant le plus à gauche dans le déclarateur et travaillez votre issue, souvenez-vous de ce [] et () Bind avant . Compte tenu de la déclaration xxx

casser comme xxx

si la déclaration avait été xxx

Puis il tomberait comme xxx

Cela vous aidera également à accumuler des déclarations complexes. Supposons que vous souhaitiez déclarer un éventail de pointeurs aux fonctions de retour des pointeurs de retour des tableaux de caractère: xxx

CDECL est un outil agréable, mais après avoir fait cet exercice à quelques reprises , vous ne devriez pas en avoir besoin.


1 commentaires

Ceci est une réponse où je souhaite que Stackoverflow ait une "réponse préférée". : - / score + = 1;



0
votes

Reportez-vous à la question n ° 5 de A 'C 'Test: Les meilleures questions 0x10 pour les programmeurs intégrés de volonté par Nigel Jones *

a) int a; // un entier

b) int * a; // un pointeur à un entier

c) int ** a; // un pointeur sur un pointeur sur un entier

d) int a [10]; // un tableau de 10 entiers

e) int * a [10]; // un tableau de 10 pointeurs à des entiers

f) int (* a) [10]; // un pointeur sur un tableau de 10 entiers

g) int (* a) (int); // un pointeur sur une fonction A qui prend un argument entier et retourne un entier

h) int (* a [10]) (int); // un tableau de 10 pointeurs à des fonctions qui prennent un argument entier et renvoient un entier

* hélas, l'article original sur Embedded.com ne peut plus être trouvé sur leur site Web.


0 commentaires