Si j'écris
int *columns[32];
8 Réponses :
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
Par curiosité, savez-vous où obtenir CDECL code>? 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
Un programme de test est illustratif, en particulier à ceux d'entre nous qui ne sont pas des avocats de langue: Il semble être un tableau de pointeurs. P> P>
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 code> installé.
La plupart des non-avocats ne pourraient pas vous dire ce que void (* (* (* (* p) [n] [m]) [O]) (char c) = 0; code> déclare sans utiliser CDECL code> ou Geordi code> 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) code> à un tableau N-Element (* p) [n] code> de m-element étaux (* p) [n] [m] code> des pointeurs (* (* p) [n] [m] [m]) code> à des tableaux d'éléments O-ols (* (* (* (* (* (* (* (* ) [N] [m]) [O] code> des pointeurs (* (* (* p) [n] [m]) [O]) code> Pour les fonctions prenant un charme code> (* (* (* (* p) [n] [m]) [O]) (char c) code> et retourner vide void (* (* (* (* (* (N] [n] ) [O]) (char c) code>
@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 i> ") -> gauche" < Pointeur sur i> "(-> droite " matrice de n tableaux de m i>") -> gauche "< Pointeur sur i>" (-> droite " tableau de O i>") -> gauche " pointeur à i>" (-> droite " Fonction prise de char i>" EOL -> gauche "< et retourner vide i>. b> mais b > 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.
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]);
Il s'agit d'un tableau de 32 pointeurs à Les règles de grammaire C Spécifiez que l'accès au tableau ( La déclaration avait été la déclaration int code> et oui, ça compte. P>
[] code>) se lie plus serré que la déséroférence ( * code>) et des déclarations d'utilisation de miroir. P>
int * colonnes [32]; code> signifie que l'expression * colonnes [n] code> (où n code> est un nombre compris entre 0 et 31) est un int code>. Cette expression est la même que * (colonnes [n]) code>. La Déclaration alloue l'espace pour 32 pointes, mais il n'y a aucun int code> s alloué et (en supposant qu'il s'agisse d'une déclaration locale de fonction) Aucun des pointeurs n'est initialisé. P>
int (* colonnes) [32]; code> alors l'expression (* colonnes) [n] code> aurait été un int Code>, ce qui signifie que le * code> Drérerefence se produit avant l'accès au tableau, les colonnes auraient donc été un pointeur sur un tableau de 32 int code> s. La déclaration aurait alloué un pointeur, mais aucun tableau de int code> s. P>
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 code> est destiné à être lu * x code> est un int code>. 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] code>, cela signifie que x [0] [3] [3] code> est un int code>. 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; code> comme " * x code> est un int code>", pas b> " x code> est un int * code> ". 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] code> ; 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] code>. Cette structure est reflétée dans la déclaration.
Voici quelques déclarations amusantes pour vous:
int *arrayOfIntP[32]; int (*pointerToArrayOf32)[32];
Un astuce est de lire de droite à gauche. p>
donné Int * cols [32]; p>
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). P>
É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 casser comme p> si la déclaration avait été p> Puis il tomberait comme p> 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: p> CDECL est un outil agréable, mais après avoir fait cet exercice à quelques reprises , vous ne devriez pas en avoir besoin. p> p> [] code> et () code> Bind avant code>. Compte tenu de la déclaration p>
Ceci est une réponse où je souhaite que Stackoverflow ait une "réponse préférée". : - / score + = 1;
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 * P>
a) int a; // un entier p>
b) int * a; // un pointeur à un entier p>
c) int ** a; // un pointeur sur un pointeur sur un entier p>
d) int a [10]; // un tableau de 10 entiers p>
e) int * a [10]; // un tableau de 10 pointeurs à des entiers p>
f) int (* a) [10]; // un pointeur sur un tableau de 10 entiers p>
g) int (* a) (int); // un pointeur sur une fonction A qui prend un argument entier et retourne un entier p>
h) int (* a [10]) (int); // un tableau de 10 pointeurs à des fonctions qui prennent un argument entier et renvoient un entier p>
* hélas, l'article original sur Embedded.com ne peut plus être trouvé sur leur site Web. P>