📜  C中的复杂声明

📅  最后修改于: 2021-05-25 23:26:06             🧑  作者: Mango

大多数时候,声明很容易阅读,但是很难读取一些涉及函数指针的声明。例如,考虑“ signal.h”中的以下声明。

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


C
1)  int (*fp) ();


C
/* Example */
 
#include 
int (*fp)();
int func(void) { printf("hello\n"); }
 
int main()
{
    fp = func;
    (*fp)();
    // fp(); // This will also call func
    return 0;
}


C
2) int (*daytab)[13]


C
/* Example */
 
#include 
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;
}


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


C
/* Example */
 
#include 
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;
}


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


C
/* Example */
 
#include 
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;
}


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


C
/* Example */
 
#include 
 
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;
}


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


C
/* Example */
 
#include 
 
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;
}


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


C
#include 
 
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;
}


让我们看看读取复杂声明的步骤。
1)将C声明转换为后缀格式,并从右向左读取。
2)要将表达式转换为后缀,请从最里面的括号开始,如果不存在最里面的括号,则从声明名称开始,然后右移。第一次遇到结尾括号时,请向左走。解析完整个括号后,便会从括号中出来。
3)继续直到解析完完整的声明。
让我们从一个简单的例子开始。以下示例摘自“ K&R”一书。

C

1)  int (*fp) ();

让我们将上面的表达式转换为后缀格式。对于上面的示例,没有最里面的括号,这就是为什么,我们将打印声明名称,即“ fp”。下一步是转到表达式的右侧,但是“ fp”的右侧没有要解析的内容,这就是为什么转到左侧。在左侧,我们找到了“ *”,现在打印了“ *”,并且没有括号。我们将获得如下的后缀表达式。

fp  *  ()  int

现在从左到右读取后缀表达式。例如fp是指向返回int的函数的指针

C

/* Example */
 
#include 
int (*fp)();
int func(void) { printf("hello\n"); }
 
int main()
{
    fp = func;
    (*fp)();
    // fp(); // This will also call func
    return 0;
}
输出
hello

让我们看看更多示例。

C

2) int (*daytab)[13]

后缀:daytab * [13] int
含义:daytab是指向13个整数的数组的指针。

C

/* Example */
 
#include 
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;
}
输出
arr[2] = 3

C

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

后缀:f [10] *(int,int)无效
含义:f是由10个指向函数的指针组成的数组(该函数采用2个int类型的参数),返回void

C

/* Example */
 
#include 
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;
}
输出
func1 = 1, 2
func2 = 3, 4
func3 = 5, 6

C

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

后缀:x()* [] *()char
含义:x是一个函数,该函数返回指向数组的指针,该指针指向返回char的函数

C

/* Example */
 
#include 
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;
}
输出

a
b
c

C

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

后缀:x [3] *()* [5]字符
含义:x是3个指向函数的指针的数组,返回5个char的数组的指针

C

/* Example */
 
#include 
 
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;
}
输出
func1 = [a, b, c, d]
func2 = [q, w, e, r]
func3 = [x, y, z, w]

C

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

后缀:arr [5] *()*()* int
含义:arr是一个由5个指向函数的指针组成的数组,该数组返回指向函数的指针,返回指向整数的指针

C

/* Example */
 
#include 
 
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;
}
输出
1
2

C

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

后缀:bsd_signal(int sig,void(* func)(int))*(int)void
含义:bsd_signal是一个函数,它的函数(即取整数作为参数并返回void),返回指针到一个函数(即取整数作为参数并返回void)整数&一个指针

C

#include 
 
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;
}
输出
sig10 exit
sig20 exit
default exit
user default exit
想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。