¿Cómo interpreto declaraciones complejas como:
int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2
¿Hay alguna regla que deba seguirse para comprender las declaraciones anteriores?
Prasoon Saurav
¿Cómo interpreto declaraciones complejas como:
int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2
¿Hay alguna regla que deba seguirse para comprender las declaraciones anteriores?
amigo
Aquí hay un gran artículo sobre cómo leer declaraciones complejas en C: http://www.codeproject.com/KB/cpp/complex_declarations.aspx
¡Me ayudó un montón!
Especialmente: debe leer la sección “La regla correcta”. Aquí cita:
int * (* (*fp1) (int) ) [10]; Esto se puede interpretar de la siguiente manera:
- Comience desde el nombre de la variable ————————– fp1
- Nada a la derecha pero ), así que ve a la izquierda para encontrar * ————– es un puntero
- Salte de paréntesis y encuentre (int) ——— a una función que toma un int como argumento
- Ir a la izquierda, buscar * —————————————- y devuelve un puntero
- Saltar poner entre paréntesis, ir a la derecha y golpear [10] ——– a una matriz de 10
- Ir a la izquierda buscar * —————————————– punteros a
- Vaya a la izquierda otra vez, encuentre int ——————————– ints.
alex b
Puedes usar cdecl
*
:
cdecl> explain int *( *( *a[5])())();
declare a as array 5 of pointer to function
returning pointer to function returning pointer to int
cdecl> explain int * (* (*fp1) (int) ) [10];
declare fp1 as pointer to function (int) returning
pointer to array 10 of pointer to int
*
Linked es un sitio web que utiliza esta herramienta de línea de comandos en el backend.
Aprendí el siguiente método hace mucho tiempo:
Comience desde el identificador de tipo (o el paréntesis interno) y muévase siguiendo una espiral tomando el elemento a la derecha primero
En caso de
int * (* (*fp1) (int) ) [10];
Puedes decir:
Resultando en:
fp1 es un puntero a una función que toma un int y devuelve un puntero a una matriz de 10 punteros a int
Dibujar la espiral real (en tu mente, al menos) ayuda mucho.
Para resolver estas declaraciones complicadas, la regla que debe tener en cuenta es que la precedencia del operador de llamada a función () y el operador de subíndice de matriz [] es mayor que el operador de desreferencia *. Obviamente, se pueden usar paréntesis ( ) para anular estas precedencias.
Ahora, calcule su declaración desde el medio, lo que significa desde el nombre del identificador.
int * (* (*fp1) (int) ) [10]; —>declaración 1
Según la regla de precedencia mencionada anteriormente, puede entenderla fácilmente al desglosar la declaración como
fp1 * (int) * [10] * En t
y léalo directamente de izquierda a derecha en inglés como “fp1 es un puntero a una función que acepta un int y devuelve un puntero a una matriz [10] de punteros a int”. Tenga en cuenta que la declaración se rompe de esta manera solo para ayudar a entenderla manualmente. El compilador NO necesita analizarla de esta manera.
Similar,
En t *( *( *[5])())(); ——–>declaración 2
se rompe como
[5] * () * () * En t
Entonces, declara “una matriz [5] de tipo punteros a función () que devuelve un puntero a una función () que a su vez devuelve un puntero a int”.
whacko__cracko
Aunque ya se ha respondido, también puede leer este artículo:
Juan Bode
Comience con el identificador más a la izquierda y avance, recordando que en ausencia de cualquier agrupación explícita []
y ()
atar antes *
p.ej:
*a[] -- is an array of pointer (*a)[] -- is a pointer to an array *f() -- is a function returning pointer (*f)() -- is a pointer to a function
Así, leemos int *(*(*fp1)(int))[10]
como:
fp1 -- fp1
*fp1 -- is a pointer
(*fp1)(int) -- to a function
taking an int parameter
*(*fp1)(int) -- returning a pointer
(*(*fp1)(int))[10] -- to a 10-element array
*(*(*fp1)(int))[10] -- of pointer
int *(*(*fp1)(int))[10] -- to int
La declaracion int *(*(*[5])())()
presenta un pequeño desafío ya que no hay identificador; normalmente ve esto en las declaraciones de funciones donde un parámetro es de ese tipo:
void foo(int *(*(*[5])())(), double);
Es el mismo principio que el sin nombre. int
parámetro en la declaración de fp1
. La matriz nos da la pista, también puede buscar la agrupación de paréntesis interna más a la izquierda.
-- unnamed
[5] -- is a 5-element array ([] binds before *)
*[5] -- of pointers
(*[5])() -- to functions
*(*[5])() -- returning pointers
(*(*[5])())() -- to functions
*(*(*[5])())() -- returning pointers
int *(*(*[5])())() -- to int
miguel rebabas
El sentido de las agujas del reloj/espiral:
* http://c-faq.com/decl/spiral.anderson.html
¡Genial! ¡No sabía que este método tenía un nombre!
– Remo.D
12 de diciembre de 2009 a las 18:40
int *( *( *[5])())();
<- ¿dónde está el nombre de la variable en esa declaración?– Andreas Grech
12 de diciembre de 2009 a las 11:20
Aunque no estoy de acuerdo: tales declaraciones son una de las razones por las que algunas personas temen y odian C y aún más C++.
– AIRE SUAVE ROJO
12 de diciembre de 2009 a las 14:15
@REDSOFTADAIR No, gente hace complejo lo simple. ¿Por qué necesita leer las declaraciones en voz alta? Solo necesita saber cómo usarlo, y está escrito en la declaración:
*(*(*fp1) (5)) [0]
es unint
y*(*(*fp1) (7)) [9]
también. Sobre C++, tengo que decir que esto ni siquiera es una cosa en comparación con los miles de diseños de inconsistencia antinaturales en C++. Puedes ver las palabras de Linus, Stallman y Knuth.– usuario26742873
12 de agosto de 2020 a las 11:02