问答题 【说明】
在嵌入式操作系统设备管理的实现上,常使用到C语言的函数指针变量,由统一的管理函数调用不同的设备驱动程序。下面的一段C语言代码是驱动管理程序 manage_device调用4个不同设备驱动程序,但没有用到函数指针变量。
【C语言代码】
/*变量与类型说明*/
#include "stdio.h"
#include "stdlib.h"
extern int sys_status;
extern int Dev_drv1(int arg1, int arg2);
extern int Dev_drv2(int arg1, int arg2);
extern int Dev_drv3(int arg1, int arg2);
extern int Dev_drv4(int arg1, iht arg2);
#define NOERROR 0

type struct {
int _fd;
} TYP_DEV_TAB;
TYP DEV_TAB dev_tab[50]= {101,99, 80, 120,};

/*程序代码*/
void manage_device(int devid, int arg1, int arg2)
{ int place ;
int ret;
for(place=0 ; place<50 ; place++)
if dev_tab [place]. fd == devid) break;
if(place>=50)
printf(" NO DEVICE fd = %d\n ",devid);
switch(dev_tab [place]._fd) {
case 80:
ret = Dev_drv3(int arg1,int arg2);
break;
case 99:
ret = Dev_drv2(int arg1,int arg2);
break;
case 101:
ret = Dev_drv1(int arg1,int arg2);
break;
case 120:
ret = Dev_drv4(int arg1,int arg2);
break;
}
if (ret!=NOERROR)
printf(" DEVICE %d error!\n ", devid);
}

int Dev_drv1(int arg1,int arg2)
{
/*局部变量声明,略*/
/*驱动程序代码,略*/
}

int Dev_drv2(int arg1,int arg2)
{
/*局部变量声明,略*/
/*驱动程序代码,略*/
}

int Dev_drv3(int arg1,int arg2)
{
/*局部变量声明,略*/
/*驱动程序代码,略*/
}

int Dev_drv4(int arg1,int arg2)
{
/*局部变量声明,略*/
/*驱动程序代码,略*/
问答题 【问题1】
请用C语言的函数指针变量,对manage_device函数进行改造,完成下面C语言代码中的(1)、(2)、(3)和(4)处的变量说明或语句,将解答填入对应栏内。
【C语言代码】
/*变量与类型说明*/
#include "stdio.h"
#include "stdlib.h"
extern int sys_status;
extern int Dev_drv1(int arg1, int arg2);
extern int Dev_drv2(int arg1, iht arg2);
extern int Dev_drv3(int arg1, int arg2);
extern int Dev_drv4(int arg1, int arg2);
#define NOERROR 0
typedef struct {
int _fd;
(1) 函数指针变量说明;/* 变量名用process */
} TYP_DEV_TAB;
TYP_DEV_TAB dev_tab[50]= {{101, Dev_drv1},{99, Dev_drv2},
{80, Dev_drv3},{120, Dev_dry4},};
/* 程序 */
void manage_device(int devid, int arg1, int arg2)
{ iht place ;
int ret;
(2) 函数指针变量说明;/*局部变量,变量名用ProcAction */
for(place=0 ; place<50 ; place++) {
if(dev_tab [place]._fd == devid) {
(3) 语句1;/* 变量名胜ProcAction, 得到具体函数的入口地址 */
break;
}
}
if(place>=50)
printf("NO DEVICE fd = %d\n",devid);
(4) 语句2;
if(ret!=NOERROR)
printf("DEVICE %d error!", devid);
}
【正确答案】
【答案解析】(1)int (*process)(int arg1,int arg2);
(2)int (*ProcAction)(int arg1,int arg2);
(3)ProcAction=dev_tab[place].process;
(4)ret=ProcAction(arg1,arg2); [解析]
本题考查对C语言中函数指针变量的理解和用法。在C语言中,可以用指针变量指向整型变量、字符串、数组、结构变量,也可以指向一个函数,对指针的用法非常灵活,也很容易出错。其中,函数指针变量为较高级的用法。
一个函数在编译时被分配给一个入口地址,这个入口地址就称为函数的指针。可以用一个指针变量指向函数,然后通过该指针变量调用此函数。
本题已将使用变量指向函数编写设备驱动程序的大部分给出,只需在对函数指针变量的声明和引用处,只需给出正确的用法即可。
问答题 【问题2】
在C语言程序中,常在某些变量的说明前加extem,如本题在变量说明中的第一条加extem int sys_stams;请说明加extem与不加extem的区别,在进行编译时会有什么样的不同处理?
【正确答案】
【答案解析】
变量加extern与不加extern的区别 在变量志明前加extern,表明为引用一个外部变量,是外部变量引用声明。
如果在一个文件中要引用另一文件中定义的全局变量,就应在变量声明前加extern
不加extern,是在本文件中定义了一个全局变量,同时可被其他文件作为外部变量引用
在进行编译时的处理 在不加extern外部变量的定义处,编译时要给变量分配地址空间。在加extern外部变量引用声明处,不给变量分配地址
[解析]
本题考查对C语言的变量声明类型的理解。在变量声明前加extem,表明为引用一个外部变量,是外部变量引用声明,不管该变量在程序的什么位置。如果在一个文件中要引用在另一文件中定义的全局变量,就应在变量声明前加extem。
如果在一个全局变量前不加extem,表明该变量是在本文件中定义的一个全局变量,同时可被其他文件作为外部变量引用。
在不加extem外部变量的定义处,编译时要给变量分配地址空间。在加extem外部变量引用声明处,不给变量分配地址。
值得注意的是,如果在全局变量的声明前都加extem,在这种情况下,编译连接时会确定一处分配一次地址空间。
问答题 【问题3】
函数的参数存放在什么地址空间中?说明其作用范围。将答案填入对应栏内。
【正确答案】
【答案解析】
函数的参数存放地址空间 函数的参数存放在进程或任务的栈空间
作用范围 在调用函数时,给函数的各参数在栈空间分配地址,函数返回时退出栈空间。所以,函数参数在函数被调用时起作用。
[解析]
本题考查对栈空间基础知识。函数的参数存放在进程或任务的栈空间中,在调用函数时,给函数的各参数在栈空间分配地址;函数返回时退出栈空间。所以,函数参数在函数被调用时起作用。
问答题 【问题4】
在设备驱动程序(函数)Dev_drv1中,对指针ptr的说明如下:
【C语文代码】
int Dev_drv1(int arg1,int arg2 )
{
struct node {
int ID;
char name [20];
int range;
} ;
struct node *ptr;
/*其他局部变量声明,略*/
ptr = (struct node *)malloc(sizeof(struct node)*100);
/*其他程序代码,略*/
}
设int为32位整数,char占8位。当对指针ptr赋完值后的值为0x3751CO,若再执行一条“ptr++;”语句,此时ptr的值为多少? (用十六进制表示)。
【正确答案】
【答案解析】ptr的值为以下均按正确对待。
0x3751DC,或3751DCH,或十六进制3751DC,或3751DC。 [解析]
本题考查对C语言指针变量的理解。在指针赋予某一变量的地址后,该指针就指向该变量所分配的地址空间。需要强调的是,指针变量是有类型的,指针的值加1,表示增加按其声明类型所占的字节数,而不是增加一个字节的地址。因此ptr++后ptr的值比原来增加28个字节,当前的值应为0x3751DC。