Je parcourais simplement du code sur Internet et j'ai trouvé ceci :
float * (*(*foo())[SIZE][SIZE])()
Comment puis-je lire cette déclaration ? Y a-t-il un ensemble spécifique de règles pour lire de telles déclarations complexes ?
Je parcourais simplement du code sur Internet et j'ai trouvé ceci :
float * (*(*foo())[SIZE][SIZE])()
Comment puis-je lire cette déclaration ? Y a-t-il un ensemble spécifique de règles pour lire de telles déclarations complexes ?
Je n'ai pas fait ça depuis un moment!
Commencez par foo
et allez à droite.
float * (*(*
<code>foo()</code>)[SIZE][SIZE])()
foo est une fonction sans arguments...
Impossible d'aller à droite car il y a une parenthèse fermante. Allons à gauche:
float * (*(
<code>* foo()</code>)[SIZE][SIZE])()
foo est une fonction sans arguments retournant un pointeur
Impossible d'aller plus à gauche, alors traversons les parenthèses et allons à droite à nouveau
float * (*``[SIZE][SIZE])()
float * (*``[SIZE])()
float * (*``)()
foo est une fonction sans arguments retournant un pointeur vers un tableau de SIZE tableaux de SIZE ...
Parenthèse fermante atteinte, allons à gauche de nouveau pour atteindre un symbole de pointeur:
float * (
<code>(( foo())[SIZE][SIZE]</code>)()
foo est une fonction sans arguments retournant un pointeur vers un tableau de SIZE tableaux de SIZE pointeurs vers ...
Encore une fois à gauche de la parenthèse, alors nous la traversons et allons à droite à nouveau:
float *``()
float *
foo est une fonction sans arguments retournant un pointeur vers un tableau de SIZE tableaux de SIZE pointeurs vers une fonction sans arguments...
Et à gauche jusqu'à la fin
<code>float ( (* foo())[SIZE][SIZE])()</code>
foo est une fonction sans arguments retournant un pointeur vers un tableau de SIZE tableaux de SIZE pointeurs vers une fonction sans arguments retournant un pointeur vers float
Et à celui qui a écrit ça, s'il vous plaît apprenez-lui à utiliser typedef
:
// Fonction qui retourne un pointeur vers un float
typedef float* PFloatFunc ();
// Tableau de pointeurs vers des fonctions PFloatFunc
typedef PFloatFunc* PFloatFuncArray2D[SIZE][SIZE];
// Fonction qui retourne un pointeur vers un PFloatFuncArray2D
PFloatFuncArray2D* foo();
Règle standard : Trouvez l'identificateur le plus à gauche et travaillez votre chemin à partir de là, en vous rappelant que []
et ()
lient avant *
:
foo -- foo
foo() -- est une fonction
*foo() -- renvoyant un pointeur
(*foo())[SIZE] -- vers un tableau de taille SIZE
(*foo())[SIZE][SIZE] -- de tableaux de taille SIZE
*(*foo())[SIZE][SIZE] -- de pointeurs
(*(*foo())[SIZE][SIZE])() -- vers des fonctions
* (*(*foo())[SIZE][SIZE])() -- renvoyant des pointeurs
float * (*(*foo())[SIZE][SIZE])(); -- vers du float
Imaginez maintenant que vous avez une série de fonctions renvoyant des pointeurs vers float
:
float *quux();
float *bar();
float *bletch();
float *blurga();
Disons que vous voulez les stocker dans un tableau 2x2 :
float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
tab
est un tableau de taille SIZE x SIZE de pointeurs vers des fonctions renvoyant des pointeurs vers float
.
Maintenant, décidons que nous voulons une fonction qui renvoie un pointeur vers ce tableau :
float *(*(*foo())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
return &tab;
}
Notez que vous pourriez avoir plusieurs fonctions qui construisent des tableaux de fonctions différentes, ou organiser les mêmes fonctions différemment :
float *(*(*qwerbl())[SIZE][SIZE])()
{
static float *(*tab[SIZE][SIZE])() = {blurga, bletch, bar, quux};
return tab;
}
C'est la seule raison à laquelle je pense pour faire quelque chose comme cela. Vous ne devriez pas voir des types comme celui-ci couramment (bien qu'ils apparaissent de temps en temps, et j'ai été coupable d'écrire quelque chose de similaire).
Qwerbl? Vous avez presque épuisé les noms de variables génériques, n'est-ce pas :-) +1 pour la logique. Et je suis sûr que les types "profondément liés" apparaissent assez souvent, mais impliquent généralement des structures ou des classes également, ce qui résout naturellement le problème de nommage - comme ce serait le cas ici en introduisant quelques typedefs.
@Kos : ouais. Je n'ai pas encore eu ma dose quotidienne de caféine, je n'ai pas pu trouver mieux.
Wikipedia a une liste de variables métasyntaxiques afin que vous ne manquiez pas : foo, bar, baz, qux, quux, corge, grault, garply, waldo, fred, plugh, xyzzy, thud.
Selon cdecl.org
declare foo as function returning pointer to array SIZE of array SIZE of pointer to function returning pointer to float
Utilisez la règle du spirale donnée par Luchian Grigore si vous voulez le décoder à la main.
En général, vous pourriez essayer cdecl.org mais vous auriez besoin de remplacer par SIZE
Disons que vous remplacez SIZE
par 12, vous obtiendriez:
déclarez foo comme une fonction renvoyant un pointeur vers un tableau 12 de tableau 12 de pointeur vers une fonction renvoyant un pointeur vers un flottant
Je ne suis pas sûr que cela vous aide vraiment !
Deux observations ici :
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
22 votes
règle en spirale
16 votes
cdecl.org
0 votes
Utiliser cdecl.org
24 votes
Vous trouvez le programmeur qui l'a écrit et vous lui demandez ce que cela signifie. Ensuite, vous dites à votre patron de le renvoyer, et vous insistez pour dire que vous ne travaillerez jamais sur le code qu'il a écrit.
0 votes
Possiblement en double stackoverflow.com/questions/3706704/…
0 votes
@juanchopanza Erreur de syntaxe...
0 votes
@Andalur [cdecl.org sur
float * (*(*foo())[SIZE][SIZE])()
](cdecl.org/?q=float%20*%20(*(*foo(%29%29[16][16]%29(%29) oùSIZE
est 16.0 votes
@LuchianGrigore La règle en spirale ne peut pas analyser cela
0 votes
@LuchianGrigore Parce que la règle de la spirale est incorrecte. Elle ne peut pas analyser
int a[5][6]
, car elle ne suit pas l'ordre de priorité