Pregunta sobre c, function-pointers – Sintaxis C para funciones que devuelven punteros a funciones.

34

Considere los siguientes typedefs:

typedef int (*f1)(float);
typedef f1 (*f2)(double);
typedef f2 (*f3)(int);

f2 Es una función que devuelve un puntero a una función. Lo mismo conf3, pero el tipo de la función, el puntero al quef3 devuelve, esf2. Como puedo definirf3 sin las typedefs? Sé que las typedefs son la forma más clara y fácil de entender de definirf3. Sin embargo, mi intención aquí es entender mejor la sintaxis de C.

Y para obtener crédito adicional, haga f3 __stdcall, f2 __cdecl y f1 __fastcall Gur
C o C ++? Porque C ++ tiene algunas formas más fáciles de expresar tales cosas. Puppy
Convenido. Yo uso una estrategia específica para ayudar con eso. Comienzo con una simple declaración que sé que es válida.explain luego crea un formulario en inglés para esa declaración. Copio y pego y extiendo cuidadosamente el formulario en inglés, añado el verbodeclareyvoila, Tengo la respuesta que busco. Robᵩ
cdecl.org solo se traduce de sintaxis c a inglés. No es muy útil para ir al otro lado, ya que tiene que redactar su declaración perfectamente en la forma que espera, y no es así como funciona el inglés o cualquier otro idioma natural. Benjamin Lindley

Tu respuesta

6   la respuesta
114

Comience con su declaración paraf1:

int (*f1)(float);

Usted quieref2 ser puntero a una función que vuelvef1, entonces sustitutof1 en la declaración anterior con la declaración def2:

int (*      f1     )(float);
            |
      +-----+-----+
      |           |
      v           v
int (*(*f2)(double))(float);

La declaración se lee como

        f2                   -- f2
       *f2                   -- is a pointer
      (*f2)(      )          -- to a function
      (*f2)(double)          --   taking a double parameter
     *(*f2)(double)          --   returning a pointer
    (*(*f2)(double))(     )  --   to a function
    (*(*f2)(double))(float)  --     taking a float parameter
int (*(*f2)(double))(float)  --     returning int

Repites el proceso paraf3:

int (*(*    f2    )(double))(float);
            |
        +---+----+
        |        |
        v        v
int (*(*(*f3)(int))(double))(float);

que se lee como

          f3                           -- f3
         *f3                           -- is a pointer
        (*f3)(   )                     -- to a function
        (*f3)(int)                     --   taking an int parameter
       *(*f3)(int)                     --   returning a pointer
      (*(*f3)(int))(      )            --   to a function
      (*(*f3)(int))(double)            --     taking a double parameter
     *(*(*f3)(int))(double)            --     returning a pointer
    (*(*(*f3)(int))(double))(     )    --     to a function
    (*(*(*f3)(int))(double))(float)    --       taking a float parameter
int (*(*(*f3)(int))(double))(float);   --       returning int
Esta respuesta debe imprimirse en masa y distribuirse en escuelas de ingeniería informática, es la forma más sencilla y mejor de entender la sintaxis de la declaración de punteros de función, ¡gracias John Bode! Ki Jéy
Cuando tu martillo es C, todo alrededor parece un pulgar ... Spook
@Tim: Es principalmente una cuestión de entender la sintaxis de la declaración, que desafortunadamente no se explica muy bien en la mayoría de las referencias. Simplemente "hizo clic" un día, y de repente las declaraciones peludas tuvieron sentido. John Bode
+1, ya que esto realmente responde a la pregunta original, que trata de la sintaxis correcta en C ... Macmade
Gracias john Me preguntaba donde has aprendido eso? ¿Hay algún buen libro que lo explique? Tim
13

En C ++, el milagro de las plantillas puede hacer esto un poco más fácil.

#include <type_traits>

std::add_pointer<
    std::add_pointer<
        std::add_pointer<
            int(float)
        >::type(double)
    >::type(int)
>::type wow;
@Macmade: Etiqueta C ++, obtiene una respuesta de C ++. Puppy
+1 para el "wow" :-) Eitan T
Esto es quizás más limpio que no usar ningún tipo de ayuda (nitypedef oadd_pointer), pero eltypedef El enfoque sigue siendo más limpio (IMHO). David Hammen
La pregunta era sobre la sintaxis de C, incluso si la publicación estaba etiquetada con C ++, por lo que no es IMHO relevante ... Pero buena respuesta, por cierto. :) Macmade
7

Al igual que con typedef, solo usted coloca la definición de su función en lugar de su nombre.

Así es cómof2 se vería como

typedef int (*(*f2)(double))(float);

Tu puedes hacerf3 como un ejercicio, ya que asumo que esto es tarea;)

La respuesta que das está disponible mediante una búsqueda en Google. Sin embargo, la sintaxis para más de un nivel (función que devuelve el puntero de la función que devuelve el indicador de la función) no es muy fácil de encontrar. Y la referencia de la tarea era injustificada. keveman
Por cierto,int (*(*f3(double))(float))(int) { return 0; } Define la función con el tipo que busco. Gracias. keveman
El Sr. downvoter necesita mejores habilidades de análisis de C Blindy
busque "puntero de función de retorno de función" y encontrará la respuesta que acaba de publicar. Sin embargo, busque "función que devuelve el puntero de la función que devuelve el puntero de la función" y no encontrará la respuesta que está buscando. keveman
0

Utilizarstd::function:

typedef std::function<int(float)> f1;
typedef std::function<f1(double)> f2;
typedef std::function<f2(int)>    f3;

o

typedef std::function<std::function<std::function<int(float)>(double)>(int)> f3;
5

Simplemente no lo hagas Se puede hacer, pero será muy confuso. Typedef's están ahí para facilitar la escritura y la lectura de este corto de código.

Una funciónf Eso no toma argumentos y devuelve un puntero a función.int (*)(float) probablemente sería algo como (no probado):

int (*f())(float);

Luego, por el resto, solo debes seguir agregando paréntesis hasta que se vea como lisp.

+1: Simplemente no lo hagas. La apariencia lispish de la respuesta de John Bode es `nuff dijo. David Hammen
4

Aprende ella regla de derecha-izquierda:

La regla "derecha-izquierda" es una regla completamente regular para descifrar las declaraciones de C. También puede ser útil para crearlos.

Preguntas relacionadas