Declaraciones complicadas en C

La mayoría de las veces, las declaraciones son fáciles de leer, pero es difícil leer algunas declaraciones que implican un puntero a funciones. Por ejemplo, considere la siguiente declaración de “signal.h”.

C

void (*bsd_signal(int, void (*)(int)))(int);

Veamos los pasos para leer declaraciones complicadas.
1) Convierta la declaración C al formato de postfijo y lea de derecha a izquierda. 
2) Para convertir una expresión a sufijo, comience desde el paréntesis más interno. Si el paréntesis más interno no está presente, comience desde el nombre de las declaraciones y vaya primero a la derecha. Cuando se encuentre por primera vez con un paréntesis final, vaya a la izquierda. Una vez que se analiza el paréntesis completo, salga del paréntesis. 
3) Continúe hasta que se haya analizado la declaración completa.
Comencemos con un ejemplo simple. Los siguientes ejemplos son del libro «K & R».

C

1)  int (*fp) ();

Convirtamos la expresión anterior al formato de postfijo. Para el ejemplo anterior, no hay paréntesis más interno, por eso imprimiremos el nombre de la declaración, es decir, «fp». El siguiente paso es ir al lado derecho de la expresión, pero no hay nada en el lado derecho de «fp» para analizar, por eso vaya al lado izquierdo. En el lado izquierdo encontramos «*», ahora imprima «*» y salga del paréntesis. Obtendremos la expresión de postfijo como se muestra a continuación.  

  fp  *  ()  int

Ahora lea la expresión postfix de izquierda a derecha. por ejemplo, fp es un puntero a la función que devuelve int

C

/* Example */
 
#include <stdio.h>
int (*fp)();
int func(void) { printf("hello\n"); }
 
int main()
{
    fp = func;
    (*fp)();
    // fp(); // This will also call func
    return 0;
}
Producción

hello

Veamos algunos ejemplos más. 
 

C

2) int (*daytab)[13]

Postfijo: daytab * [13] int 
Significado: daytab es un puntero a una array de 13 enteros.

C

/* Example */
 
#include <stdio.h>
int (*daytab)[13];
int arr[13] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
int main()
{
    daytab = &arr;
    printf("arr[2] = %d\n", (*daytab)[2]);
    return 0;
}
Producción

arr[2] = 3

C

3) void (*f[10]) (int, int)

Postfijo: f[10] * (int, int) void 
Significado: f es una array de 10 punteros a la función (que toma 2 argumentos de tipo int) que devuelve void
 

C

/* Example */
 
#include <stdio.h>
void (*f[10])(int, int);
void func1(int a, int b)
{
    printf("func1 = %d, %d\n", a, b);
}
void func2(int p, int q)
{
    printf("func2 = %d, %d\n", p, q);
}
void func3(int x, int y)
{
    printf("func3 = %d, %d\n", x, y);
}
int main()
{
    f[0] = func1;
    f[1] = func2;
    f[2] = func3;
    (*f[0])(1, 2);
    (*f[1])(3, 4);
    (*f[2])(5, 6);
    return 0;
}
Producción

func1 = 1, 2
func2 = 3, 4
func3 = 5, 6

C

4) char (*(*x())[]) ()

Postfijo: x() * [] *() char 
Significado: x es una función que devuelve un puntero a una array de punteros a una función que devuelve un carácter

C

/* Example */
 
#include <stdio.h>
char func1() { return 'a'; }
char func2() { return 'b'; }
char func3() { return 'c'; }
 
char (*xarr[])() = { func1, func2, func3 };
char (*(*x())[])() { return &xarr; }
 
int main()
{
    printf("%c\n", ((*(x()))[0])());
    printf("%c\n", ((*(x()))[1])());
    printf("%c\n", ((*(x()))[2])());
    return 0;
}
Producción

a
b
c

C

5) char (*(*x[3])())[5]

Postfijo: x[3] *() * [5] char 
Significado: x es una array de 3 punteros a la función que devuelve el puntero a la array de 5 caracteres

C

/* Example */
 
#include <stdio.h>
 
typedef char charray5[5];
 
charray5 carr1 = { 'a', 'b', 'c', 'd', '\0' };
charray5 carr2 = { 'q', 'w', 'e', 'r', '\0' };
charray5 carr3 = { 'x', 'y', 'z', 'w', '\0' };
 
charray5* func1() { return &carr1; }
charray5* func2() { return &carr2; }
charray5* func3() { return &carr3; }
 
char (*(*x[3])())[5] = { func1, func2, func3 };
 
int main()
{
    printf("func1 = [%c, %c, %c, %c]\n",
           ((*(x[0]))())[0][0], ((*(x[0]))())[0][1],
           ((*(x[0]))())[0][2], ((*(x[0]))())[0][3]);
    printf("func2 = [%c, %c, %c, %c]\n",
           ((*(x[1]))())[0][0], ((*(x[1]))())[0][1],
           ((*(x[1]))())[0][2], ((*(x[1]))())[0][3]);
    printf("func3 = [%c, %c, %c, %c]\n",
           ((*(x[2]))())[0][0], ((*(x[2]))())[0][1],
           ((*(x[2]))())[0][2], ((*(x[2]))())[0][3]);
    return 0;
}
Producción

func1 = [a, b, c, d]
func2 = [q, w, e, r]
func3 = [x, y, z, w]

C

6) int *(*(*arr[5])()) ()

Postfijo: arr[5] *() *() * int 
Significado: arr es una array de 5 punteros a funciones que devuelven puntero a función que devuelven puntero a entero
 

C

/* Example */
 
#include <stdio.h>
 
int a = 1;
int b = 2;
int* func1() { return &a; }
int* func2() { return &b; }
 
int* (*funcp1())() { return func1; }
int* (*funcp2())() { return func2; }
int* (*(*arr[5])())() = { funcp1, funcp2 };
 
int main()
{
    printf("%d\n", *(*(*arr[0])())());
    printf("%d\n", *(*(*arr[1])())());
    return 0;
}
Producción

1
2

C

7) void (*bsd_signal(int sig, void (*func)(int)))(int);

Postfijo: bsd_signal(int sig, void(*func)(int)) * (int) void 
Significado: bsd_signal es una función que toma enteros y un puntero a una función (que toma enteros como argumento y devuelve vacío) y devuelve puntero a una función (que toma un número entero como argumento y devuelve vacío)

C

#include <stdio.h>
 
void on_sig10_exit(int u) { printf("sig10 exit\n"); }
void on_sig20_exit(int u) { printf("sig20 exit\n"); }
void default_exit(int u) { printf("default exit\n"); }
void user_default_exit(int u)
{
    printf("user default exit\n");
}
 
void (*exit_by)(int);
 
void (*bsd_signal(int sig, void (*func)(int)))(int)
{
    switch (sig) {
    case 10:
        return on_sig10_exit;
    case 20:
        return on_sig20_exit;
    default:
        if (func == NULL)
            return default_exit;
        else
            return user_default_exit;
    }
}
 
int main()
{
    (bsd_signal(10, NULL))(0);
    (bsd_signal(20, NULL))(0);
    (bsd_signal(30, NULL))(0);
    (bsd_signal(30, user_default_exit))(0);
    return 0;
}
Producción

sig10 exit
sig20 exit
default exit
user default exit

Este artículo fue compilado por «Narendra Kangralkar» y revisado por el equipo de GeeksforGeeks. Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *