¿Cómo se determina la precedencia en los punteros C?

14

Me he encontrado con dos declaraciones de puntero que tengo problemas para entender. Mi comprensión de las reglas de precedencia es algo como esto:

Operator             Precedence             Associativity
(), [ ]                  1                  Left to Right
*, identifier            2                  Right to Left
Data type                3

Pero incluso dado esto, parece que no puedo entender cómo evaluar los siguientes ejemplos correctamente:

Primer ejemplo

float * (* (*ptr)(int))(double **,char c)

Mi evaluación:

  1. *(ptr)
  2. (int)
  3. *(*ptr)(int)
  4. *(*(*ptr)(int))

Luego,

  1. double **
  2. char c

Segundo ejemplo

unsigned **( * (*ptr) [5] ) (char const *,int *)
  1. *(ptr)
  2. [5]
  3. *(*ptr)[5]
  4. *(*(*ptr)[5])
  5. **(*(*ptr)[5])

¿Cómo debería leerlos?

trapaank
fuente
1
Aquí se trata sobre cómo maneja sus características un idioma.

Respuestas:

7

Mi conjetura para el primero : ptr es un puntero a una función que toma como parámetro un int, y devuelve un puntero a una función que toma como parámetros un puntero a puntero para duplicar y un carácter, y devuelve un puntero para flotar.

Interpretación :

(* ptr) (int)

dice que ptr es un puntero a una función que toma un int como argumento. Para descubrir qué devuelve esa función, necesitamos expandir nuestra vista:

(* (* ptr) (int))

Esto significa que la función devuelve un puntero a otra función. Los parámetros de esa otra función son:

(doble **, char c)

y vuelve

flotador *

Y para el segundo : ptr es un puntero a una matriz de cinco punteros a funciones que toman como parámetros un puntero constante a char y un puntero a int, devolviendo un puntero a un puntero de int sin signo.

Interpretación :

(* (* ptr) [5])

declara ptr como puntero a una matriz de cinco punteros a una función que toma

(char const *, int *)

como argumentos y volviendo

sin firmar **

Daniel Scocco
fuente
7

Puede probar el método 'La espiral en sentido horario' para comprender estas declaraciones locas:

http://c-faq.com/decl/spiral.anderson.html

También escribí un blog sobre esto aquí:

http://www.kalekold.net/index.php?post=4

Gary Willoughby
fuente
Gracias por tu respuesta. Pero en el método de la espiral en sentido horario, ¿por dónde empezar en mi caso? En los ejemplos dados en el enlace hay ejemplos simples. No puedo hacer coincidir mi ecuación con ese método.
trapaank
1
debe comenzar desde su identificador: ptr. tendrá: "ptr es un puntero a una función que toma un int y devuelve un puntero a una función que lleva un puntero a un puntero a un doble y un char y devuelve un puntero a un flotador". prueba el spyral y obtendrás lo mismo.
Remo.D
1

Es un puntero de función. La persona que lo escribió podría haber hecho un mejor uso de typedefs para haberlo aclarado.

En efecto, es un puntero para funcionar con estos parámetros. float * myfunc (doble **, char)

Michael Shaw
fuente
44
Mi apuesta es que la persona que lo escribió es el maestro.
mouviciel
Esperemos que no sea el maestro, porque no necesitas saber una mierda como esta. Aunque supongo que un buen maestro primero te daría una bofetada con expresiones como estas, permitiéndote rascarte la cabeza tratando de interpretarlas y luego mostrarte cómo usar typedef correctamente.