Declaraciones complejas

2 minutos de lectura

avatar de usuario
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?

  • 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 un inty *(*(*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


avatar de usuario
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:

  1. Comience desde el nombre de la variable ————————– fp1
  2. Nada a la derecha pero ), así que ve a la izquierda para encontrar * ————– es un puntero
  3. Salte de paréntesis y encuentre (int) ——— a una función que toma un int como argumento
  4. Ir a la izquierda, buscar * —————————————- y devuelve un puntero
  5. Saltar poner entre paréntesis, ir a la derecha y golpear [10] ——– a una matriz de 10
  6. Ir a la izquierda buscar * —————————————– punteros a
  7. Vaya a la izquierda otra vez, encuentre int ——————————– ints.

avatar de usuario
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:

  • fp1 es un (nada a la derecha, así que muévase a la izquierda)
  • puntero a (salir del paréntesis interior
  • una función que toma como argumento a int (la 1ra por la derecha)
  • y devuelve un puntero a (salir del paréntesis)
  • una matriz de 10 elementos de tipo
  • puntero a (no queda nada a la derecha)
  • En t

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”.

avatar de usuario
whacko__cracko

Aunque ya se ha respondido, también puede leer este artículo:

http://unixwiz.net/techtips/reading-cdecl.html

avatar de usuario
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

avatar de usuario
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

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad