cC语言第16天,声明器、函数指针与数组

一、声明器

提供标识符与类型信息,用于声明一个标识符的语法被称作声明器。

1.声明数组B

1.元素类型:int[10];

2.数组名:B;

3.元素个数:5

按照公式,我们写出如下形式的声明:int[10] B[5];

接下来,把元素类型中的方括号移动到最右边,int B[5][10];

 

2.函数声明器

int*func(char *p,double d);

上面的函数声明器声明了一个函数,这个函数的参数与返回值如下:

1.第一个参数为char*类型;

2.第二个参数为double类型的;

3.返回值为int*的函数。

别忘了,函数声明时可以省略参数变量名。

int*func(char*,double);

类似于其他声明器,声明器中将标识符去掉即可得到这个标识符的类型。上面的声明器声明了一个类型为int*(char*,double)的函数。

 

3.声明器中的优先级

优先级从高到低依次如下:

1.括号()

2.函数声明的()与数组声明的[]优先级相同。

3.指针声明的*

例如:标识符id,int*(*id)[4]

1.优先计算括号()内的指针*。所以,id是一个指针。

2.接着计算数组[],上一步的指针指向一个数组。

3.现在轮到指针*了,上一步的数组的元素为指针。

4.数组元素指向int。

id标识符的类型为指针数组指针,它指向一个int*[4]的数组。而这个数组中的元素为int*类型的指针。

 

那么如何使用id呢?

1.*id先使用取值运算符*,将id从指针int*(*)[4]转换为数组int*[4]。

2.(*id)[0]对数组使用下标运算符,获得下标对应的数组元素,这里以0为例。

3.*(*id)[0]上一步中数组元素是一个指针,再使用取值运算符*,获得目标数据对象,即int。

id声明为:int*(*id)[4]

id使用为:*(*id)[0],且表达式结果为int

 

二、函数指针与数组

1.函数指针

int(*func)(char*,double);

声明器中出现了两对括号,请注意区分它们。(*func)为单纯的括号,优先级最高。而(char*,double)是函数声明的括号。

我们在上面说过int func(char*,double)是一个函数,那么int(*func)(char*,double)中优先计算(*func),所以int(*func)(char*,double)为一个函数指针。

 

由于历史原因,有一部分程序员它们不喜欢对函数指针取值之后再使用它们。而是把函数指针直接当做函数类型使用。

int(*p)(char*)=print;//函数指针

int=(*p)("HelloWorld")//对函数指针取值后,函数指针p还原成了函数。就可以把它当做函数print一样使用即可。

int n=p("HelloWorld");//p当做函数直接使用printf("%d\n",n);

而C语言标准收录了这两种写法,因此(*p)("HelloWorld")等价于p("HelloWorld")。很显然,后者更加方便,省略了星号和括号。

 

2.变式:函数指针数组

int(*func[10])(char*,double);

1.优先计算括号()内的*func[10]。

2.数组[]被优先计算。所以,这是一个数组。

3.接着计算*func[10]中的指针*,上一步的数组的元素为指针。

4.括号计算完毕,开始计算函数(char*,double)。上一步的指针指向一个函数。

5.函数的参数为char*与double。标识符func是一个数组,而每个数组元素为指针。

数组元素指向类型为int(char*,double)的函数。这是元素为函数指针组成的数组,它被称作函数指针数组。

 

我们再举一个更加复杂的例子,用于突出函数指针数组的灵活性。

void TheShawshankRedemption()

{printf("1.肖申克的救赎\n");}

void Zootopia()

{printf("2.疯狂动物城\n");}

void Interstellar()

{printf("3.星际穿越\n");}

void TheLegendof1900()

{printf("4.海上钢琴师\n");}

void TheMatrix()

{printf("5.黑客帝国\n");}

 

问题:现在有5部电影,由观众输入电影的序号,建立一个播放列表。之后,根据播放列表,依次播放电影。

先将播放这5部电影的函数放入数组中。接着需要用户输入一串电影序号。

int main()

{

void(*movies[5])()={TheShawshankRedemption,Zootopia,Interstellar,TheLegendof1900,TheMatrix};

char playList[21];//我们暂时将播放列表长度最大限制为20,那么字符串playList需要21个元素,别忘了字符串有结尾标记'\0'。

scanf("%s",playList);//输入播放序号列表

for(int i=0;playList[i] != '\0'; i++)//利用循环依次读取每一个元素

/*经过循环,我们得到的是单个的字符的ASCII码,需要将其转换为数值。

由于ASCII编码中,0到9的ASCII码是连续的。通过求输入字符与字符'0'的差,即可将ASCII转为数组。

另外,电影序号从1开始,而数组下标是从0开始的,这里需要稍微适配一下。*/

{char num=playList[i];//当前电影序号

 

num=num-'0';//将字符转为数值

num - -;//播放列表从1开始,而数组从0开始

movies[num]();//根据序号找到对应的函数并执行}

}

 

posted @ 2022-09-23 17:53  纯爱暴打ntr  阅读(126)  评论(0)    收藏  举报