2010-08-05 4 views
9

Est-ce correct?Comment déclarez-vous un pointeur sur une fonction qui renvoie un pointeur vers un tableau de valeurs int en C/C++?

int (*(*ptr)())[]; 

Je sais que cela est trivial, mais je regardais un ancien test au sujet de ce genre de constructions, et cette combinaison particulière n'a pas été sur le test et il m'a vraiment rendre fou; Je dois juste m'assurer. Y a-t-il une règle claire et solide compréhensible à ce genre de déclarations? (c'est-à-dire: pointeur vers ... tableau de .. pointeurs vers ... fonctions que .... etc etc) Merci!

R

+4

+1 pour le titre de tête qui m'a fait mal au cerveau! (Plus le nom: P) – Russell

+0

Pourrait probablement faire une réponse, mais rappelez-vous la règle en spirale dans le sens des aiguilles d'une montre, cela fonctionne dans les deux sens, juste ajuster pour la direction. – jer

+0

Est-ce que boost :: function quelque chose que vous accepteriez? –

Répondre

13

The right-left rule facilite.

int (*(*ptr)())[]; peut être interprété comme

début du nom de la variable ------------------------------- ptr

Rien à droite, mais ) donc aller à gauche pour trouver * -------------- est un pointeur

sauter des parenthèses et rencontrent () --- -------- à une fonction qui ne prend aucun argument (dans le cas d'un nombre d'arguments non spécifié)

Allez à gauche, trouvez * --------------------------- --------------------- et renvoie un pointeur

Jump mettre des parenthèses, allez à droite et appuyez sur [] --------- - à un tableau de

Allez encore à gauche, trouvez int --------------------------------- ---- ints.

+3

Il n'y a rien de facile à ce sujet. J'aime utiliser typedefs pour le décomposer un peu. –

+0

Notez cependant que l'exemple n'est pas une déclaration valide - pour en faire un, la taille du tableau doit être spécifiée. – caf

+2

@caf: Cela fait du type un type incomplet mais vous pouvez toujours utiliser un pointeur vers un type incomplet dans une déclaration. –

0

Voici ma solution ...

int** (*func)(); 

Functor retourne un tableau de int * 's. Ce n'est pas aussi compliqué que votre solution.

1

En utilisant cdecl vous obtenez les éléments suivants

cdecl> declare a as pointer to function returning pointer to array of int; 
Warning: Unsupported in C -- 'Pointer to array of unspecified dimension' 
    (maybe you mean "pointer to object") 
int (*(*a)())[] 

This question de C-faq est similaire, mais fournit 3 approches pour résoudre le problème.

5

Dans la plupart des situations où vous souhaitez renvoyer un pointeur vers un tableau, la chose la plus simple à faire est de renvoyer un pointeur vers le premier élément du tableau. Ce pointeur peut être utilisé dans les mêmes contextes qu'un nom de tableau et ne fournit pas plus ou moins d'indirection que de renvoyer un pointeur de type "pointeur sur tableau", en effet il contiendra la même valeur de pointeur.

Si vous suivez ceci, vous voulez un pointeur vers une fonction renvoyant un pointeur vers un int. Vous pouvez construire ceci (la construction de déclarations est plus facile que l'analyse).

Pointeur vers int:

int *A; 

Fonction pointeur de retour à int:

int *fn(); 
pointeur

à fonction renvoyant un pointeur vers int:

int *(*pfn)(); 

Si vous voulez vraiment renvoyer un pointeur vers une fonction renvoyant un pointeur sur un tableau de int, vous pouvez suivre le même processus.

Array of int:

int A[]; 

pointeur sur un tableau de int:

int (*p)[]; 

Fonction pointeur retour ...:

int (*fn())[]; 

pointeur sur fn ...:

int (*(*pfn)())[]; 

qui est ce que vous avez.

1

Si vous vous sentez comme de la tricherie:

typedef int(*PtrToArray)[5]; 
PtrToArray function(); 

int i = function; 

que sur les rendements Compiler gcc: invalid conversion from 'int (*(*)())[5]' to 'int'. Le premier bit est le type que vous recherchez. Bien sûr, une fois que vous avez votre PtrToArray typedef, tout l'exercice devient plutôt trivial, mais parfois cela devient pratique si vous avez déjà le nom de la fonction et vous avez juste besoin de le coller quelque part. Et, pour une raison quelconque, vous ne pouvez pas compter sur la supercherie de gabarit pour cacher les détails sanglants de vous.

Si votre compilateur prend en charge, vous pouvez aussi le faire:

typedef int(*PtrToArray)[5]; 
PtrToArray function(); 

template<typename T> void print(T) { 
    cout << __PRETTY_FUNCTION__ << endl; 
} 

print(function); 

qui, sur ma boîte informatique, produit void function(T) [with T = int (* (*)())[5]]

Être capable de lire les types est très utile, car la compréhension des erreurs du compilateur dépend souvent de votre capacité à comprendre ce que signifient toutes ces parenthèses. Mais les rendre vous-même est moins utile, IMO.

2

Ce n'est pas le cas. Il suffit de le diviser en deux typedefs: un pour le pointeur vers le tableau int, et un pour le pointeur vers les fonctions. Quelque chose comme:

typedef int (*IntArrayPtr_t)[]; 
typedef IntArrayPtr_t (*GetIntArrayFuncPtr_t)(void); 

Ceci est non seulement plus lisible, il est également plus facile de déclarer/définir les fonctions que vous allez assigner la variable:

IntArrayPtr_t GetColumnSums(void) 
{ .... } 

Bien sûr, cela suppose que c'était une situation réelle, et non une question d'entrevue ou un devoir. Je dirais toujours que c'est une meilleure solution pour ces cas, mais c'est seulement moi.:)

Questions connexes