2010-08-05 17 views
9

¿Es esto correcto?¿Cómo declaras un puntero a una función que devuelve un puntero a una matriz de valores int en C/C++?

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

Sé que esto es trivial, pero yo estaba buscando en una vieja prueba sobre este tipo de construcciones, y esta combinación particular no estaba en la prueba y es realmente me está volviendo loca; Solo tengo que asegurarme. ¿Existe una regla comprensible clara y sólida para este tipo de declaraciones? (es decir: puntero a ... una matriz de ... punteros a ... funciones que .... etc.) ¡Gracias!

R

+4

¡+1 por el título principal que hizo que me doliera el cerebro! (Más el nombre: P) – Russell

+0

Probablemente podría hacer de esto una respuesta, pero recuerde la regla de la espiral en el sentido de las agujas del reloj, funciona en ambos sentidos, simplemente ajuste la dirección. – jer

+0

¿Es boost :: function algo que aceptaría? –

Respuesta

13

The right-left rule hace que sea fácil.

int (*(*ptr)())[]; se puede interpretar como

inicio del nombre de la variable ------------------------------- ptr

Nada a la derecha, pero por lo ) ir a la izquierda para encontrar * -------------- es un puntero

Salto desde paréntesis y se encuentran () --- -------- a una función que no toma argumentos (en caso de C no especificado, número de argumentos)

Ir a la izquierda, buscar * --------------------------- --------------------- y devuelve un puntero

Salto de paréntesis, vaya a la derecha y marque [] --------- - a una matriz de

Ir a la izquierda de nuevo, encontrar int --------------------------------- ---- ints.

+3

No hay nada fácil en esto. Me gusta usar typedefs para descomponerlo un poco. –

+0

Tenga en cuenta que el ejemplo no es una declaración válida; para hacerlo uno, debe especificarse el tamaño de la matriz. – caf

+2

@caf: Hace que el tipo sea incompleto pero aún puede usar un puntero a un tipo incompleto en una declaración. –

0

aquí está mi solución ...

int** (*func)(); 

Functor devolver una matriz de int * 's. No es tan complicado como tu solución.

1

Usando cdecl se obtiene el siguiente

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 es similar, pero ofrece 3 enfoques para resolver el problema.

5

En casi todas las situaciones en las que desea devolver un puntero a una matriz, lo más simple es devolver un puntero al primer elemento de la matriz. Este puntero se puede usar en los mismos contextos que un nombre de matriz; no proporciona más o menos indirección que devolver un puntero de tipo "puntero a matriz"; de hecho, mantendrá el mismo valor de puntero.

Si sigue esto, quiere un puntero a una función que devuelve un puntero a int. Puede construir esto (la construcción de declaraciones es más fácil que el análisis).

Puntero a int:

int *A; 

función de puntero de volver a int:

int *fn(); 

puntero a una función que devuelve un puntero a int:

int *(*pfn)(); 

Si realmente desea devolver un puntero a una función que devuelve un puntero a una matriz de int, puede seguir el mismo proceso.

matriz de int:

int A[]; 

puntero a matriz de int:

int (*p)[]; 

función de puntero de regresar ...:

int (*fn())[]; 

Puntero a fn ...:

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

que es lo que tienes.

1

si se siente como hacer trampa:

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

int i = function; 

Compilación de que en los rendimientos de gcc: invalid conversion from 'int (*(*)())[5]' to 'int'. El primer bit es el tipo que estás buscando.

Por supuesto, una vez que tienes tu PtrToArray typedef, todo el ejercicio se vuelve más trivial, pero a veces esto es útil si ya tienes el nombre de la función y solo necesitas pegarlo en alguna parte. Y, por la razón que sea, no puede confiar en el engaño de la plantilla para ocultarle los detalles sangrientos.

Si su compilador soporta, también se puede hacer esto:

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

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

print(function); 

Lo cual, en mi caja de ordenador, produce void function(T) [with T = int (* (*)())[5]]

Ser capaz de leer los tipos es bastante útil, ya que la comprensión de los errores del compilador a menudo depende de tu capacidad para descubrir qué significan todos esos paréntesis. Pero hacerlos tú mismo es menos útil, IMO.

2

No es así. Simplemente divídalo en dos typedefs: uno para puntero a int array, y otro para puntero a funciones. Algo así como:

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

Esto no sólo es más fácil de leer, sino que también hace que sea más fácil para declarar/definir las funciones que se van a asignar a la variable:

IntArrayPtr_t GetColumnSums(void) 
{ .... } 

Por supuesto, esto supone que esto era una situación del mundo real, y no una pregunta de entrevista o tarea. Todavía diría que esta es una solución mejor para esos casos, pero ese soy solo yo.:)

Cuestiones relacionadas