69 votos

Declaración de complejo C

Yo estaba pasando por algo de código en internet y encontré esto:

float * (*(*foo())[SIZE][SIZE])()

¿Cómo leer esta declaración? ¿Hay un conjunto específico de reglas para leer estas declaraciones complejas?

119voto

Kos Puntos 29125

No he hecho esto en un rato!

Comienzan con foo e ir a la derecha.

float * (*(*foo())[SIZE][SIZE])()

foo es una función sin argumentos...

No puede ir a la derecha, puesto que hay un paréntesis de cierre. Ir a la izquierda:

float * (*(* foo())[SIZE][SIZE])()

foo es una función sin argumentos devuelve un puntero

No puede ir a la izquierda, de manera que vamos a cruzar los paréntesis e ir de nuevo a la derecha

float * (*(* foo())[SIZE][SIZE])()
float * (*(* foo())[SIZE][SIZE])()
float * (*(* foo())[SIZE][SIZE])()

foo es una función sin argumentos devuelve un puntero a una matriz de matrices de TAMAÑO de TAMAÑO ...

paréntesis de cierre llegado, de nuevo a la izquierda para llegar a un puntero símbolo:

float * (*(* foo())[SIZE][SIZE])()

foo es una función sin argumentos devuelve un puntero a una matriz de matrices de TAMAÑO de TAMAÑO de los punteros ...

El paréntesis izquierdo de nuevo, así que cruzamos y nos dirigimos de nuevo a la derecha

float *( *(* foo())[SIZE][SIZE])()
float *( *(* foo())[SIZE][SIZE])()

foo es una función sin argumentos devuelve un puntero a una matriz de matrices de TAMAÑO de TAMAÑO de los punteros a una función sin argumentos...

Y dejar para el final

float * ( *(* foo())[SIZE][SIZE])()

foo es una función sin argumentos devuelve un puntero a una matriz de matrices de TAMAÑO de TAMAÑO de los punteros a una función sin argumentos devuelve un puntero a float


Y quien escribió que, por favor, que le enseñe a usar typedef:

// function that returns a pointer to float
typedef float* PFloatFunc (); 

// array of pointers to PFloatFunc functions
typedef PFloatFunc* PFloatFuncArray2D[SIZE][SIZE];

// function that returns a pointer to a PFloatFuncArray2D
PFloatFuncArray2D* foo();

99voto

John Bode Puntos 33046

Regla estándar: encuentra a la izquierda de identificador y su forma de trabajo, recordando que [] y () enlazar antes *:

            foo                      -- foo
            foo()                    -- is a function
           *foo()                    -- returning a pointer
          (*foo())[SIZE]             -- to a SIZE-element array
          (*foo())[SIZE][SIZE]       -- of SIZE-element arrays
         *(*foo())[SIZE][SIZE]       -- of pointers
        (*(*foo())[SIZE][SIZE])()    -- to functions
      * (*(*foo())[SIZE][SIZE])()    -- returning pointers
float * (*(*foo())[SIZE][SIZE])();   -- to float

Así que imagine que usted tiene un montón de funciones que devuelven punteros float:

float *quux();
float *bar();
float *bletch();
float *blurga();

Digamos que usted desea almacenar en una tabla de 2x2:

float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};

tab es de un TAMAÑO x TAMAÑO del array de punteros a funciones que devuelven punteros float.

Ahora vamos a decidir queremos una función que devuelve un puntero a la tabla:

float *(*(*foo())[SIZE][SIZE])()
{
  static float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
  return &tab;
}

Tenga en cuenta que usted puede tener varias funciones que construir las tablas de las diferentes funciones, u organizar las mismas funciones de forma diferente:

float *(*(*qwerbl())[SIZE][SIZE])()
{
  static float *(*tab[SIZE][SIZE])() = {blurga, bletch, bar, quux};
  return tab;
}

que es la única razón que se me ocurre hacer algo como esto. Usted no debería ver tipos como este en el salvaje muy a menudo (aunque sí de los cultivos de vez en cuando, y yo he sido culpable de escribir algo similar atroz).

6voto

Clement J. Puntos 2579

Según cdecl.org

declarar foo como función volviendo puntero al array tamaño de matriz de tamaño de puntero a función devolviendo puntero a float

Utilice la regla espiral dada por Luchian Grigore si quieres descifrarlo con la mano.

4voto

QuentinUK Puntos 995

La mejor cosa que hacer es convertir a una serie de definiciones de tipos.

typedef float * fnReturningPointerToFloat();
typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE];
fnArray* foo();

3voto

Component 10 Puntos 4512

Generalmente, usted podría tratar de cdecl.org pero habrá que sustituir SIZE

Dicen que usted swap SIZE 12, se obtendría:

declarar foo como función que devuelve puntero a un array de 12 de matriz de 12 de puntero de función que devuelve puntero a float

No estoy seguro de que realmente ayuda!

Dos observaciones aquí:

  1. Supongo que este código no tiene un comentario al lado explicando cuál es el propósito de la misma era (es decir, no la explicación técnica de lo que es, pero lo que es la consecución de un funcional / perspectiva de negocio) Si un programador debe usar algo tan complejo como este, que debe ser lo suficientemente buena para explicar a los futuros mantenedores de lo que es su propósito.
  2. Ciertamente en C++ hay más obvia, y probablemente la forma más segura de lograr la misma cosa.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X