C语言中的复杂声明

大多数情况下,声明都很容易阅读,但有些涉及函数指针的声明很难阅读。例如,从“信号H”考虑下面的声明。

null

C

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


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

C

1) int (*fp) ();


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

  fp  *  ()  int

现在从左到右阅读后缀表达式。e、 g.fp是指向返回int的函数的指针

C

/* Example */
#include <stdio.h>
int (*fp)();
int func( void ) { printf ( "hello" ); }
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 <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" , (*daytab)[2]);
return 0;
}


输出

arr[2] = 3

C

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


后缀:f[10]*(int,int)void 意思是:f是一个10指针的数组,指向返回void的函数(它接受两个int类型的参数)

C

/* Example */
#include <stdio.h>
void (*f[10])( int , int );
void func1( int a, int b)
{
printf ( "func1 = %d, %d" , a, b);
}
void func2( int p, int q)
{
printf ( "func2 = %d, %d" , p, q);
}
void func3( int x, int y)
{
printf ( "func3 = %d, %d" , 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, 2func2 = 3, 4func3 = 5, 6

C

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


后缀:x()*[]*()字符 意思:x是一个函数,返回指向返回字符的函数的指针数组

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" , ((*(x()))[0])());
printf ( "%c" , ((*(x()))[1])());
printf ( "%c" , ((*(x()))[2])());
return 0;
}


输出

abc

C

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


后缀:x[3]*()*[5]字符 意思是:x是一个由3个指针组成的数组,函数返回指向5个字符数组的指针

C

/* Example */
#include <stdio.h>
typedef char charray5[5];
charray5 carr1 = { 'a' , 'b' , 'c' , 'd' , ' ' };
charray5 carr2 = { 'q' , 'w' , 'e' , 'r' , ' ' };
charray5 carr3 = { 'x' , 'y' , 'z' , 'w' , ' ' };
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]" ,
((*(x[0]))())[0][0], ((*(x[0]))())[0][1],
((*(x[0]))())[0][2], ((*(x[0]))())[0][3]);
printf ( "func2 = [%c, %c, %c, %c]" ,
((*(x[1]))())[0][0], ((*(x[1]))())[0][1],
((*(x[1]))())[0][2], ((*(x[1]))())[0][3]);
printf ( "func3 = [%c, %c, %c, %c]" ,
((*(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 <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" , *(*(*arr[0])())());
printf ( "%d" , *(*(*arr[1])())());
return 0;
}


输出

12

C

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


后缀:bsd_信号(int-sig,void(*func)(int))*(int)void 含义:bsd_信号是一个函数,它接受整数&指向函数的指针(接受整数作为参数并返回void),然后返回指向函数的指针(接受整数作为参数并返回void)

C

#include <stdio.h>
void on_sig10_exit( int u) { printf ( "sig10 exit" ); }
void on_sig20_exit( int u) { printf ( "sig20 exit" ); }
void default_exit( int u) { printf ( "default exit" ); }
void user_default_exit( int u)
{
printf ( "user default exit" );
}
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 exitsig20 exitdefault exituser default exit

本文由“Narendra Kangralkar”编辑,Geeksforgeks团队审阅。如果您发现任何不正确的地方,请发表评论,或者您想分享有关上述主题的更多信息。

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享