struct在Keil的注意事项
代码中用到了函数指针,该函数指针有一个参数,参数类型也是一个指针,见下面代码片段的Tset2那行中会报错。使用Keil编译时出现了“error C212: indirect call: parameters do not fit within registers”错误。
typedef struct
{
void (*Test1)(unsigned char a,unsigned char b);
void (*Test2)(unsigned char a,unsigned char* b);
unsigned char (Test3)(unsigned char *a,unsigned char b);
}Test_TypeDefStruct;
原因
与大多数16位和32位微控制器不同,8051不是基于堆栈的架构。 当参数不能放入CPU寄存器时,Keil Cx51编译器默认使用直接的内存位置来传递参数。 这种技术生成非常高效的代码,但限制了可以传递给间接调用的函数的参数。 当通过函数指针传递给函数的形参不适合寄存器时,编译器无法确定将形参放在内存中的哪个位置,因为函数在调用时是未知的。
解决方法一
使用可重入函数属性 reentrant 创建可重入函数。编译器模拟了一种基于堆栈的体系结构,它可以将几乎无限数量的参数传递给间接调用的函数。例如:
typedef struct
{
void (*Test1)(unsigned char a,unsigned char b);
void (*Test2)(unsigned char a,unsigned char* b)reentrant;
unsigned char (*Test3)(unsigned char *a,unsigned char b)reentrant;
}Test_TypeDefStruct;
在后面加reentrant就可以了,但他只能解决Test3,不能解决Test2.不是很好的解决方法。下面的解决方法最为推荐。
解决方法二
限制参数的数量和类型,使它们都适合CPU寄存器。当您需要最佳性能或程序大小非常重要时,请执行此操作。
typedef struct
{
void (*Test1)(unsigned char a,unsigned char b);
void (*Test2)(unsigned char a,unsigned char data* b);
unsigned char (*Test3)(unsigned char data*a,unsigned char b);
}Test_TypeDefStruct;
在指针前面告诉他的空间位置,比如data、xdata。